﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ОписаниеПеременных

&НаКлиенте
Перем ТекущийВыбранныйРеквизит;

#КонецОбласти

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	УстановитьУсловноеОформление();
	ПроверитьВерсиюИРежимСовместимостиПлатформы();
	Параметры.Свойство("ДополнительнаяОбработкаСсылка", ДополнительнаяОбработкаСсылка);
	
	КонтекстныйВызов = ТипЗнч(Параметры.МассивОбъектов) = Тип("Массив");
	
	Элементы.ФормаНазад.Видимость = Ложь;
	ЗапретРедактированияВстроен = Метаданные.НайтиПоПолномуИмени("ОбщийМодуль.ЗапретРедактированияРеквизитовОбъектовКлиент") <> Неопределено;
	
	Если КонтекстныйВызов Тогда
		ВыполнитьДействияПриКонтекстномОткрытии();
	Иначе
		Если Не ЭтоПолноправныйПользователь() Тогда
			ВызватьИсключение НСтр("ru = 'Для открытия обработки требуется право администрирования.'")
		КонецЕсли;
		Заголовок = НСтр("ru = 'Групповое изменение реквизитов'");
		ЗаполнитьСписокТиповОбъектов();
	КонецЕсли;
	
	ЗагрузитьНастройкиОбработки();
	
	СформироватьПояснениеОНастроенныхИзменениях();
	ОбновитьВидимостьЭлементов();
	
	Если Не КонтекстныйВызов Тогда
		РежимОткрытияОкна = РежимОткрытияОкнаФормы.Независимый;
	КонецЕсли;
	
	// Проверяем наличие поля ИспользуемоеИмяФайла у объекта обработки.
	ОбработкаОбъект  = РеквизитФормыВЗначение("Объект");
	СтруктураОбъекта = Новый Структура("ИспользуемоеИмяФайла", Неопределено);
	ЗаполнитьЗначенияСвойств(СтруктураОбъекта, ОбработкаОбъект);
	
	// Если поле ИспользуемоеИмяФайла есть - это внешняя обработка.
	Если Не ЗначениеЗаполнено(ДополнительнаяОбработкаСсылка)
	   И ЗначениеЗаполнено(СтруктураОбъекта.ИспользуемоеИмяФайла)
	   И Не СтрНачинаетсяС(СтруктураОбъекта.ИспользуемоеИмяФайла, "e1cib/")
	   И Не СтрНачинаетсяС(СтруктураОбъекта.ИспользуемоеИмяФайла, "e1cib\") Тогда
		ПутьКФайлуВнешнейОбработкиНаКлиенте = СтруктураОбъекта.ИспользуемоеИмяФайла;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
#Если ВебКлиент Тогда
	Если ЗначениеЗаполнено(ПутьКФайлуВнешнейОбработкиНаКлиенте) Тогда
		ТекстОшибки = НСтр("ru = 'Для этого действия требуется запустить клиентское приложение'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
#КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
	
	Если ВРег(ИсточникВыбора.ИмяФормы) = ВРег(ПолноеИмяФормы("ДополнительныеПараметры")) Тогда
		
		ПерезаполнитьСтруктуруРеквизитовОбъекта = Ложь;
		Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
			Объект.РежимРазработчика = ВыбранноеЗначение.РежимРазработчика;
			ОтключитьСвязиПараметровВыбора = ВыбранноеЗначение.ОтключитьСвязиПараметровВыбора;
			Если УчитыватьИерархию И ОбрабатыватьРекурсивно <> ВыбранноеЗначение.ОбрабатыватьРекурсивно Тогда
				ОбрабатыватьРекурсивно = ВыбранноеЗначение.ОбрабатыватьРекурсивно;
				ПерезаполнитьСтруктуруРеквизитовОбъекта = Истина;
				ИнициализироватьКомпоновщикНастроек();
			КонецЕсли;
			Объект.ИзменятьВТранзакции = ВыбранноеЗначение.ИзменятьВТранзакции;
			Объект.ПрерыватьПриОшибке  = ВыбранноеЗначение.ПрерыватьПриОшибке;
			
			Если Объект.ПоказыватьСлужебныеРеквизиты <> ВыбранноеЗначение.ПоказыватьСлужебныеРеквизиты Тогда
				Объект.ПоказыватьСлужебныеРеквизиты = ВыбранноеЗначение.ПоказыватьСлужебныеРеквизиты;
				ПерезаполнитьСтруктуруРеквизитовОбъекта = Истина;
				ЗаполнитьСписокТиповОбъектов();
			КонецЕсли;
			
			Если ПерезаполнитьСтруктуруРеквизитовОбъекта И Не ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
				СохраненныеНастройки = Неопределено;
				ЗагрузитьМетаданныеОбъекта(Истина, СохраненныеНастройки);
				Если СохраненныеНастройки <> Неопределено И Объект.ТипОперации <> "ВыполнитьАлгоритм" Тогда
					УстановитьНастройкуИзменения(СохраненныеНастройки);
				КонецЕсли;
			КонецЕсли;
			
			ОбновитьВидимостьЭлементов();
			СохранитьНастройкиОбработки(Объект.ИзменятьВТранзакции, Объект.ПрерыватьПриОшибке, ОбрабатыватьРекурсивно);
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте
Процедура ВидИзменяемыхОбъектовНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
	ОписаниеОповещения = Новый ОписаниеОповещения("ВидИзменяемыхОбъектовВыборСделан", ЭтотОбъект);
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("ВыбранныеТипы", ВидыИзменяемыхОбъектов);
	ПараметрыФормы.Вставить("ПоказыватьСкрытые", Объект.ПоказыватьСлужебныеРеквизиты);
	ОткрытьФорму(ПолноеИмяФормы("ВыборВидаОбъектов"), ПараметрыФормы, , , , , ОписаниеОповещения);
КонецПроцедуры

&НаКлиенте
Процедура ПредставлениеИзменяемыхОбъектовПриИзменении(Элемент)
	ВыбранныйТип = Элементы.ПредставлениеИзменяемыхОбъектов.СписокВыбора.НайтиПоЗначению(ПредставлениеИзменяемыхОбъектов);
	Если ВыбранныйТип = Неопределено Тогда
		Для Каждого Тип Из Элементы.ПредставлениеИзменяемыхОбъектов.СписокВыбора Цикл
			Если СтрНайти(НРег(Тип.Представление), НРег(ПредставлениеИзменяемыхОбъектов)) = 1 Тогда
				ВыбранныйТип = Тип;
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если ВыбранныйТип = Неопределено Тогда
		ПредставлениеИзменяемыхОбъектов = ПредставлениеИзменяемыхОбъектов();
	Иначе
		ПредставлениеИзменяемыхОбъектов = ВыбранныйТип.Представление;
		ВидыИзменяемыхОбъектов = ВыбранныйТип.Значение;
		ВыбранныеОбъектыВКонтексте.Очистить();
		ПерестроитьИнтерфейсФормыДляВыбранногоВидаОбъектов();
		Если Не КонтекстныйВызов Тогда
			СохранитьВидыИзменяемыхОбъектов(ВидыИзменяемыхОбъектов, АдресСпискаВыбранных);
		КонецЕсли;	
	КонецЕсли;
	
	Алгоритм = ПредставлениеИзменяемыхОбъектов;
	
КонецПроцедуры

&НаКлиенте
Процедура ВидОперацииПриИзменении(Элемент)
	
	Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
		Элементы.СтраницыВидОперации.ТекущаяСтраница = Элементы.ПроизвольныйАлгоритм;
		Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Выполнить'");
		Элементы.РанееИзмененныеРеквизиты.Видимость = Ложь;
		Элементы.Алгоритмы.Видимость = Истина;
		Элементы.РеквизитыСтрокаПоиска.Видимость = Ложь;
	Иначе
		Элементы.СтраницыВидОперации.ТекущаяСтраница = Элементы.ИзменяемыеРеквизиты;
		Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Изменить реквизиты'");
		Элементы.РанееИзмененныеРеквизиты.Видимость = Истина;
		Элементы.Алгоритмы.Видимость = Ложь;
		Элементы.РеквизитыСтрокаПоиска.Видимость = Истина;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура СоставОбъектаПриСменеСтраницы(Элемент, ТекущаяСтраница)
	Элементы.РеквизитыСтрокаПоиска.Видимость = (ТекущаяСтраница = Элементы.Реквизиты);
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыКомпоновщикНастроекНастройкиОтбор

&НаКлиенте
Процедура ОбновитьНадписи()
	ОбновитьНадписиСервер();
КонецПроцедуры

&НаСервере
Процедура ОбновитьНадписиСервер()
	ОбновитьНадписьКоличествоВыбранных();
	СформироватьПояснениеОНастроенныхИзменениях();
	Алгоритм = ПредставлениеИзменяемыхОбъектов;
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОбъектыКоторыеНеУдалосьИзменить

&НаКлиенте
Процедура ОбъектыКоторыеНеУдалосьИзменитьПередНачаломИзменения(Элемент, Отказ)
	Отказ = Истина;
	Если ТипЗнч(Элемент.ТекущиеДанные.Объект) <> Тип("Строка") Тогда
		ПоказатьЗначение(, Элемент.ТекущиеДанные.Объект);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОбъектыКоторыеНеУдалосьИзменитьПриАктивизацииСтроки(Элемент)
	Если Элемент.ТекущиеДанные <> Неопределено Тогда
		Причина = Элемент.ТекущиеДанные.Причина;
	КонецЕсли;
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыРеквизитыОбъекта

&НаКлиенте
Процедура РеквизитыОбъектаПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
	Если Поле <> Неопределено И Поле.Имя = Элементы.РеквизитыОбъектаЗначение.Имя 
		И РеквизитыОбъекта.НайтиПоИдентификатору(Строка).ДопустимыеТипы.СодержитТип(Тип("Строка"))
		И Не СтрНачинаетсяС(РеквизитыОбъекта.НайтиПоИдентификатору(Строка).Значение, "'") Тогда
		СтандартнаяОбработка = Ложь;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура РеквизитыОбъектаПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
	ОписаниеРеквизита = РеквизитыОбъекта.НайтиПоИдентификатору(ПараметрыПеретаскивания.Значение[0]);
	ШаблонВставки = "[%1]";
	
	ТекстДляВставки = ПодставитьПараметрыВСтроку(ШаблонВставки, ОписаниеРеквизита.Представление);
	ТекущиеДанные = РеквизитыОбъекта.НайтиПоИдентификатору(Строка);
	Если Не ПустаяСтрока(ТекущиеДанные.Значение) Тогда
		ТекстДляВставки = "+" + ТекстДляВставки;
	КонецЕсли;
	ТекущиеДанные.Значение = Строка(ТекущиеДанные.Значение) + ТекстДляВставки;
	Если Не СтрНачинаетсяС(СокрЛ(ТекущиеДанные.Значение), "=") Тогда
		ТекущиеДанные.Значение = "=" + ТекущиеДанные.Значение;
	КонецЕсли;
	ТекущиеДанные.Изменять = Истина;
КонецПроцедуры

&НаКлиенте
Процедура РеквизитыОбъектаЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	ТекущиеДанные = Элементы.РеквизитыОбъекта.ТекущиеДанные;
	Если ТекущиеДанные.ДопустимыеТипы.Типы().Количество() = 1 И ТекущиеДанные.ДопустимыеТипы.СодержитТип(Тип("Строка")) Тогда
		СтандартнаяОбработка = Ложь;
		ПодключитьОбработчикОжидания("РедактироватьФормулу", 0.1, Истина);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция ЕстьОшибкиВВыражениях()
	Результат = Ложь;
	Для Индекс = 0 По РеквизитыОбъекта.Количество() - 1 Цикл
		ОписаниеРеквизита = РеквизитыОбъекта[Индекс];
		Если ОписаниеРеквизита.Изменять И ТипЗнч(ОписаниеРеквизита.Значение) = Тип("Строка") И СтрНачинаетсяС(ОписаниеРеквизита.Значение, "=") Тогда
			ТекстОшибки = "";
			Если ЕстьОшибкаВВыражении(ОписаниеРеквизита.Значение, ТекстОшибки) Тогда
				Результат = Истина;
				Сообщение = Новый СообщениеПользователю;
				Сообщение.Поле = ПодставитьПараметрыВСтроку("РеквизитыОбъекта[%1].Значение", Формат(Индекс, "ЧГ=0"));
				Сообщение.Текст = ТекстОшибки;
				Сообщение.Сообщить();
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура Изменить(Команда)
	
	Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
		
		ПраваВыполненияКода = ДоступныеПраваВыполнениеКода();
		
		Если Не ПраваВыполненияКода.ДоступноВыполнениеКода Тогда
			Возврат;
		КонецЕсли;
		
		Если Не ПраваВыполненияКода.ДоступноВыполнениеКодаВНебезопасномРежиме И Объект.РежимВыполнения = 1 Тогда
			Объект.РежимВыполнения = 0; // Переключаем на безопасный режим
		КонецЕсли;
		
	КонецЕсли;
	
	НазначениеКнопки = "Изменить";
	Если ВыполняетсяОбработка Тогда
		НазначениеКнопки = "Прервать";
	ИначеЕсли ОбработкаЗавершена Или Элементы.Страницы.ТекущаяСтраница = Элементы.ИзменениеОбъектов Тогда
		НазначениеКнопки = "Закрыть";
		Если ОбъектыКоторыеНеУдалосьИзменить.Количество() > 0 Тогда
			НазначениеКнопки = "Повторить";
		КонецЕсли;
	КонецЕсли;
	
	Если НазначениеКнопки = "Закрыть" Тогда
		Закрыть();
		Возврат;
	КонецЕсли;
	
	Если НазначениеКнопки = "Прервать" Тогда
		Если ТекущееСостояниеИзменения = Неопределено Или ДлительнаяОперация = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ТекущееСостояниеИзменения.ПрерватьИзменение = Истина;
		Элементы.ФормаИзменить.Доступность = Ложь;
		Если Не ДлительнаяОперация.Статус = "Выполнено" Тогда
			ЗавершитьИзменениеОбъектов();
		КонецЕсли;
		Возврат;
	КонецЕсли;
	
	Если НазначениеКнопки = "Изменить" Тогда
		Если Не ЕстьВыбранныеОбъекты() Тогда
			ПоказатьПредупреждение(, НСтр("ru = 'Не указаны элементы для изменения'"));
			Возврат;
		КонецЕсли;
		
		Если ЕстьОшибкиВВыражениях() Тогда
			Возврат;
		КонецЕсли;
	
		Если ЕстьНастроенныеОтборы() Тогда
			ВыполнитьИзменениеПроверкаОтбораВыполнена();
		Иначе
			ТекстВопроса = НСтр("ru = 'Отбор не задан. Изменить все элементы?'");
			ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьИзменениеПроверкаОтбораВыполнена", ЭтотОбъект);
			ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ОКОтмена, , , НСтр("ru = 'Изменение элементов'"));
		КонецЕсли;
		
		Возврат;
	КонецЕсли;
	
	Если НазначениеКнопки = "Повторить" Тогда
		ВыполнитьИзменениеПроверкиВыполнены();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура Назад(Команда)
	
	НазадСервер();
	
КонецПроцедуры

&НаКлиенте
Процедура НастроитьПараметрыИзменения(Команда)
	
	ПараметрыФормы = Новый Структура;
	
	ПараметрыФормы.Вставить("ИзменятьВТранзакции",            Объект.ИзменятьВТранзакции);
	ПараметрыФормы.Вставить("ОбрабатыватьРекурсивно",         ОбрабатыватьРекурсивно);
	ПараметрыФормы.Вставить("ПрерыватьПриОшибке",             Объект.ПрерыватьПриОшибке);
	ПараметрыФормы.Вставить("УчитыватьИерархию",              УчитыватьИерархию);
	ПараметрыФормы.Вставить("ПоказыватьСлужебныеРеквизиты",   Объект.ПоказыватьСлужебныеРеквизиты);
	ПараметрыФормы.Вставить("КонтекстныйВызов",               КонтекстныйВызов);
	ПараметрыФормы.Вставить("РежимРазработчика",              Объект.РежимРазработчика);
	ПараметрыФормы.Вставить("ОтключитьСвязиПараметровВыбора", ОтключитьСвязиПараметровВыбора);
		
	ОткрытьФорму(ПолноеИмяФормы("ДополнительныеПараметры"), ПараметрыФормы, ЭтотОбъект);
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// ПОДКЛЮЧАЕМЫЕ ОБРАБОТЧИКИ

&НаКлиенте
Процедура Подключаемый_ЗначениеПриИзменении(ПолеФормы)
	ТекущиеДанные = ПолеФормы.Родитель.ТекущиеДанные;
	ТекущиеДанные.Изменять = ЗначениеЗаполнено(ТекущиеДанные.Значение);
	ОбновитьСчетчикиИзменяемыхРеквизитов(ПолеФормы.Родитель);
	ПодключитьОбработчикОжидания("ОбновитьПояснениеОНастроенныхИзменениях", 0.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_ПриИзмененииФлажка(ПолеФормы)
	ОбновитьСчетчикиИзменяемыхРеквизитов(ПолеФормы.Родитель);
	ПодключитьОбработчикОжидания("ОбновитьПояснениеОНастроенныхИзменениях", 0.1, Истина);
КонецПроцедуры

// Параметры:
//   Команда - КомандаФормы
//
&НаКлиенте
Процедура Подключаемый_УстановитьНастройку(Команда)
	
	Если СтрНачинаетсяС(Команда.Имя, "Алгоритмы") Тогда
		МестоРазмещенияКоманд = Элементы.Алгоритмы;
		ШаблонИмениКоманды = МестоРазмещенияКоманд.Имя + "НастройкаИзменений";
		ИндексКоманды = Число(Сред(Команда.Имя, СтрДлина(ШаблонИмениКоманды) + 1));
		КодАлгоритма = ИсторияАлгоритмовСписок[ИндексКоманды].Значение;
		Алгоритм = ИсторияАлгоритмовСписок[ИндексКоманды].Представление;
		СформироватьПояснениеОНастроенныхИзменениях();
	Иначе
		МестоРазмещенияКоманд = Элементы.РанееИзмененныеРеквизиты;
		ШаблонИмениКоманды = МестоРазмещенияКоманд.Имя + "НастройкаИзменений";
		ИндексКоманды = Число(Сред(Команда.Имя, СтрДлина(ШаблонИмениКоманды) + 1));
		УстановитьНастройкуИзменения(ИсторияОперацийСписок[ИндексКоманды].Значение);
		СформироватьПояснениеОНастроенныхИзменениях();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_ПередНачаломИзменения(Элемент, Отказ)
	
	УстановитьОграниченияВыбираемыхТиповИПараметрыВыбораЗначения(Элемент);
	Если (Элемент.ТекущийЭлемент = Элементы.РеквизитыОбъектаЗначение
		Или Элемент.ТекущийЭлемент = Элементы.РеквизитыОбъектаИзменять)
		И Элемент.ТекущиеДанные.ЗаблокированныйРеквизит Тогда
			Отказ = Истина;
			ТекущийВыбранныйРеквизит = Элемент.ТекущиеДанные;
			ПодключитьОбработчикОжидания("РазрешитьРедактированиеРеквизитов", 0.1, Истина);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаКлиенте
Процедура ОбновитьПояснениеОНастроенныхИзменениях()
	СформироватьПояснениеОНастроенныхИзменениях();
КонецПроцедуры

&НаКлиенте
Процедура РеквизитыОбъектаЗначениеЗавершениеВыбора(Формула, ТекущиеДанные) Экспорт
	Если Формула = Неопределено Тогда
		Возврат;
	КонецЕсли;
	Если Не СтрНачинаетсяС(Формула, "=") Тогда
		Формула = "=" + Формула;
	КонецЕсли;
	ТекущиеДанные.Значение = Формула;
	ТекущиеДанные.Изменять = Истина;
КонецПроцедуры

&НаСервере
Процедура УстановитьУсловноеОформление()

	УсловноеОформление.Элементы.Очистить();

	// Информация об автонумерации. Эта настройка должна быть всегда первой.
	
	Элемент = УсловноеОформление.Элементы.Добавить();
	
	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.РеквизитыОбъектаЗначение.Имя);
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Изменять");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = Истина;
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.ЭтоСтандартныйРеквизит");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = Истина;
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Значение");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
	
	ГруппаОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
	ГруппаОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
	
	ОтборЭлемента = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Имя");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = "Код";
	
	ОтборЭлемента = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Имя");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = "Номер";
	
	Элемент.Оформление.УстановитьЗначениеПараметра("Текст", ПояснениеПоАвтонумерации);
	Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Серый);
	
	// Заблокированный реквизит
	
	Элемент = УсловноеОформление.Элементы.Добавить();

	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.РеквизитыОбъектаПредставление.Имя);

	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.ЗаблокированныйРеквизит");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = Истина;

	//@skip-check new-color
	Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", Новый Цвет(192, 192, 192)); // АПК:1346 - автономная обработка не может использовать стили
	
	// Пояснения по связанным реквизитам
	
	Для Каждого Реквизит Из РеквизитыОбъекта Цикл
		Элемент = УсловноеОформление.Элементы.Добавить();
		
		ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
		ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.РеквизитыОбъектаЗначение.Имя);

		ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Имя");
		ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
		ОтборЭлемента.ПравоеЗначение = Реквизит.Имя;
		
		ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Значение");
		ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
		
		ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.Изменять");
		ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
		ОтборЭлемента.ПравоеЗначение = Ложь;
		
		ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("РеквизитыОбъекта.ПредставлениеСвязейПараметровВыбора");
		ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
		
		Элемент.Оформление.УстановитьЗначениеПараметра("Текст", Реквизит.ПредставлениеСвязейПараметровВыбора);
		Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Серый);
	КонецЦикла;
	
	Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
		Для Каждого Реквизит Из ЭтотОбъект[ТабличнаяЧасть.Значение] Цикл
			УстановитьУсловноеФорматированиеРеквизитаТабличнойЧасти(Реквизит, ТабличнаяЧасть);
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//   Реквизит - Структура:
//   * Имя - Строка
//   ПредставлениеСвязейПараметровВыбора - Строка
//   ТабличнаяЧасть - ЭлементСпискаЗначений
//
&НаСервере
Процедура УстановитьУсловноеФорматированиеРеквизитаТабличнойЧасти(Реквизит, ТабличнаяЧасть)
	Элемент = УсловноеОформление.Элементы.Добавить();
	
	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(ТабличнаяЧасть.Значение + "Значение");

	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ТабличнаяЧасть.Значение + ".Имя");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = Реквизит.Имя;
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ТабличнаяЧасть.Значение + ".Значение");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ТабличнаяЧасть.Значение + ".Изменять");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = Ложь;
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ТабличнаяЧасть.Значение + ".ПредставлениеСвязейПараметровВыбора");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
	
	Элемент.Оформление.УстановитьЗначениеПараметра("Текст", Реквизит.ПредставлениеСвязейПараметровВыбора);
	Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Серый);
КонецПроцедуры


&НаКлиенте
Процедура ВыполнитьИзменениеПроверкаОтбораВыполнена(РезультатВопроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если РезультатВопроса = КодВозвратаДиалога.Отмена Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ЕстьНастроенныеИзменения() И Объект.ТипОперации = "ВвестиЗначения" Тогда
		ТекстВопроса = НСтр("ru = 'Изменения не настроены. Выполнить перезапись элементов без изменений?'");
		ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьИзменениеПроверкиВыполнены", ЭтотОбъект);
		ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ОКОтмена, , , НСтр("ru = 'Изменение элементов'"));
	Иначе
		ВыполнитьИзменениеПроверкиВыполнены();
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция ЕстьНастроенныеОтборы()
	Для Каждого ЭлементОтбора Из КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
		Если ЭлементОтбора.Использование Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	Возврат Ложь;
КонецФункции

&НаКлиенте
Функция ПолноеИмяФормы(Имя)
	ЧастиИмени = СтрРазделить(ИмяФормы, ".");
	ЧастиИмени[3] = Имя;
	Возврат СтрСоединить(ЧастиИмени, ".");
КонецФункции

&НаСервере
Процедура ВыполнитьДействияПриКонтекстномОткрытии()
	
	ШаблонЗаголовка = НСтр("ru = 'Изменение выделенных элементов ""%1"" (%2)'");
	
	ТипыОбъектов = Новый СписокЗначений;
	Для Каждого ПереданныйОбъект Из Параметры.МассивОбъектов Цикл
		ОбъектМетаданных = ПереданныйОбъект.Метаданные();
		ИмяОбъекта = ОбъектМетаданных.ПолноеИмя();
		Если ТипыОбъектов.НайтиПоЗначению(ИмяОбъекта) = Неопределено Тогда
			ТипыОбъектов.Добавить(ИмяОбъекта, ОбъектМетаданных.Представление());
		КонецЕсли;
	КонецЦикла;
	
	ПредставлениеТипа = Параметры.МассивОбъектов[0].Метаданные().Представление();
	Если ТипыОбъектов.Количество() > 1 Тогда
		ПредставлениеТипа = "";
		ШаблонЗаголовка = НСтр("ru = 'Изменение выделенных элементов (%2)'");
	КонецЕсли;
	
	КоличествоОбъектов = Параметры.МассивОбъектов.Количество();
	Заголовок = ПодставитьПараметрыВСтроку(ШаблонЗаголовка, ПредставлениеТипа, КоличествоОбъектов);
	
	// При отсутствии права сохранения настроек необходимо спрятать весь функционал работы с настройками.
	Элементы.РанееИзмененныеРеквизиты.Видимость = ПравоДоступа("СохранениеДанныхПользователя", Метаданные);
	
	ВидыИзменяемыхОбъектов = СтрСоединить(ТипыОбъектов.ВыгрузитьЗначения(), ",");
	
	// Подгружаем историю операций с данным типом объектов.
	ЗагрузитьИсториюОпераций();
	ЗаполнитьПодменюРанееИзмененныеРеквизиты();
	
	// Объект иерархический
	УчитыватьИерархию = ОбъектМетаданныхИерархический(Параметры.МассивОбъектов[0]);
	ИерархияГрупп = ИерархияГруппИЭлементов(Параметры.МассивОбъектов[0]);
	
	ВыбранныеОбъектыВКонтексте.ЗагрузитьЗначения(Параметры.МассивОбъектов);
	ИнициализироватьКомпоновщикНастроек();
	
	ЗагрузитьМетаданныеОбъекта();
	
	ПредставлениеИзменяемыхОбъектов = ПредставлениеИзменяемыхОбъектов();
	ОбновитьНадписьКоличествоВыбранных();
	
	Элементы.ПредставлениеИзменяемыхОбъектов.ТолькоПросмотр = Истина;
	
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьИзменениеПроверкиВыполнены(РезультатВопроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если РезультатВопроса = КодВозвратаДиалога.Отмена Тогда
		Возврат;
	КонецЕсли;
	
	ТекущееСостояниеИзменения = Неопределено;
	УстановитьКнопкиНаВремяИзменения(Истина);
	ПерейтиНаСтраницуИзмененияОбъектов();
	ОбъектыКоторыеНеУдалосьИзменить.Очистить();
	
	ПодключитьОбработчикОжидания("ИзменитьОбъекты", 0.1, Истина);
	
КонецПроцедуры

&НаСервере
Функция ЕстьНастроенныеИзменения()
	Возврат ИзменяемыеРеквизиты().Количество() > 0 Или ИзменяемыеТабличныеЧасти().Количество() > 0;
КонецФункции

&НаСервере
Процедура ДобавитьИзменениеВИсторию(СтруктураИзменения, ПредставлениеИзменения)
	
	Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
		Настройки = ХранилищеОбщихНастроекЗагрузить("ГрупповоеИзменениеОбъектов", 
			"ИсторияАлгоритмов/" + ВидыИзменяемыхОбъектов);
		
		Если Настройки = Неопределено Тогда
			Настройки = Новый Массив;
		Иначе
			Для Индекс = 0 По Настройки.ВГраница() Цикл
				Если Настройки.Получить(Индекс).Представление = ПредставлениеИзменения Тогда
					Настройки.Удалить(Индекс);
					Прервать;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		
		Настройки.Вставить(0, Новый Структура("Изменение, Представление", СтруктураИзменения, ПредставлениеИзменения));
		
		Если Настройки.Количество() > 20 Тогда
			Настройки.Удалить(19);
		КонецЕсли;
		
		ХранилищеОбщихНастроекСохранить("ГрупповоеИзменениеОбъектов", "ИсторияАлгоритмов/" + ВидыИзменяемыхОбъектов, Настройки);
		
		ЗагрузитьИсториюОпераций();
		ЗаполнитьПодменюРанееИзмененныеРеквизиты();

		Возврат;
	КонецЕсли;
	
	Настройки = ХранилищеОбщихНастроекЗагрузить("ГрупповоеИзменениеОбъектов", 
		"ИсторияИзменений/" + ВидыИзменяемыхОбъектов);
	
	Если Настройки = Неопределено Тогда
		Настройки = Новый Массив;
	Иначе
		Для Индекс = 0 По Настройки.ВГраница() Цикл
			Если Настройки.Получить(Индекс).Представление = ПредставлениеИзменения Тогда
				Настройки.Удалить(Индекс);
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Настройки.Вставить(0, Новый Структура("Изменение, Представление", СтруктураИзменения, ПредставлениеИзменения));
	
	Если Настройки.Количество() > 20 Тогда
		Настройки.Удалить(19);
	КонецЕсли;
	
	ХранилищеОбщихНастроекСохранить("ГрупповоеИзменениеОбъектов", "ИсторияИзменений/" + ВидыИзменяемыхОбъектов, Настройки);
	
	ЗагрузитьИсториюОпераций();
	ЗаполнитьПодменюРанееИзмененныеРеквизиты();
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьИсториюОпераций()
	
	ИсторияОперацийСписок.Очистить();
	
	ИсторияИзменений = ХранилищеОбщихНастроекЗагрузить("ГрупповоеИзменениеОбъектов", "ИсторияИзменений/" + ВидыИзменяемыхОбъектов);
	Если ИсторияИзменений <> Неопределено И ТипЗнч(ИсторияИзменений) = Тип("Массив") Тогда
		Для Каждого Настройка Из ИсторияИзменений Цикл
			ИсторияОперацийСписок.Добавить(Настройка.Изменение, Настройка.Представление);
		КонецЦикла;
	КонецЕсли;
	
	ИсторияАлгоритмовСписок.Очистить();
	
	ИсторияИзменений = ХранилищеОбщихНастроекЗагрузить("ГрупповоеИзменениеОбъектов", "ИсторияАлгоритмов/" + ВидыИзменяемыхОбъектов);
	Если ИсторияИзменений = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого Настройка Из ИсторияИзменений Цикл
		ИсторияАлгоритмовСписок.Добавить(Настройка.Изменение, Настройка.Представление);
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ВопросРазблокированияРеквизита(ВыбранныйРеквизит)
	
	Кнопки = Новый СписокЗначений;
	Кнопки.Добавить(КодВозвратаДиалога.Да, НСтр("ru = 'Разблокировать'"));
	ТекстВопроса = ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Для того чтобы не допустить рассогласования данных в программе,
			|реквизит ""%1"" не доступен для редактирования.
			|
			|Перед тем, как разрешить его редактирование, рекомендуется оценить последствия,
			|проверив все места использования выбранных элементов в программе.
			|
			|Разблокировать реквизит ""%1"" для изменения?'"),
		ВыбранныйРеквизит.Представление);
	
	Кнопки.Добавить(КодВозвратаДиалога.Отмена, НСтр("ru = 'Отмена'"));
	
	ОписаниеОповещения = Новый ОписаниеОповещения("ВопросРазблокированияРеквизитаЗавершение", ЭтотОбъект, ВыбранныйРеквизит);
	ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, Кнопки, , КодВозвратаДиалога.Да, НСтр("ru = 'Реквизит заблокирован'"));
	
КонецПроцедуры

&НаКлиенте
Процедура ВопросРазблокированияРеквизитаЗавершение(Ответ, ОписаниеРеквизита) Экспорт
	
	Если Ответ = КодВозвратаДиалога.Да Тогда
		ОписаниеРеквизита.ЗаблокированныйРеквизит = Ложь;
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УстановитьПараметрыВыбораСервер(ПараметрыВыбора, ПараметрыВыбораМассив)
	
	Для Индекс = 1 По СтрЧислоСтрок(ПараметрыВыбора) Цикл
		ПараметрыВыбораСтрока      = СтрПолучитьСтроку(ПараметрыВыбора, Индекс);
		ПараметрыВыбораМассивСтрок = СтрРазделить(ПараметрыВыбораСтрока, ";");
		ИмяПоляОтбора = СокрЛП(ПараметрыВыбораМассивСтрок[0]);
		ИмяТипа       = СокрЛП(ПараметрыВыбораМассивСтрок[1]);
		XMLСтрока     = СокрЛП(ПараметрыВыбораМассивСтрок[2]);
		
		Если Тип(ИмяТипа) = Тип("ФиксированныйМассив") Тогда
			Массив = Новый Массив;
			XMLСтрокаМассив = СтрРазделить(XMLСтрока, "#");
			Для Каждого Элемент Из XMLСтрокаМассив Цикл
				ЭлементМассив = СтрРазделить(Элемент, "*");
				ЗначениеЭлемента = XMLЗначение(Тип(ЭлементМассив[0]), ЭлементМассив[1]);
				Массив.Добавить(ЗначениеЭлемента);
			КонецЦикла;
			Значение = Новый ФиксированныйМассив(Массив);
		Иначе
			Значение = XMLЗначение(Тип(ИмяТипа), XMLСтрока);
		КонецЕсли;
		
		ПараметрыВыбораМассив.Добавить(Новый ПараметрВыбора(ИмяПоляОтбора, Значение));
	КонецЦикла;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура СохранитьНастройкиОбработки(ИзменятьВТранзакции, ПрерыватьПриОшибке, ОбрабатыватьРекурсивно)
	
	Если Не ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураНастроек = СтруктураНастроек();
	СтруктураНастроек.ИзменятьВТранзакции    = ИзменятьВТранзакции;
	СтруктураНастроек.ПрерыватьПриОшибке     = ПрерыватьПриОшибке;
	СтруктураНастроек.ОбрабатыватьРекурсивно = ОбрабатыватьРекурсивно;
	ХранилищеОбщихНастроекСохранить("Обработка.ГрупповоеИзменениеОбъектов", "", СтруктураНастроек);
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура СохранитьВидыИзменяемыхОбъектов(ВидыИзменяемыхОбъектов, АдресСпискаВыбранных)
	
	ОчиститьВременноеХранилищеСпискаВыбранных(АдресСпискаВыбранных);
	
	Если Не ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
		Возврат;
	КонецЕсли;
	ХранилищеОбщихНастроекСохранить("ГрупповоеИзменениеОбъектов", "ВидыИзменяемыхОбъектов", ВидыИзменяемыхОбъектов);
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция СтруктураНастроек()
	
	СтруктураНастроек = Новый Структура;
	СтруктураНастроек.Вставить("ИзменятьВТранзакции",    Ложь);
	СтруктураНастроек.Вставить("ПрерыватьПриОшибке",     Ложь);
	СтруктураНастроек.Вставить("ОбрабатыватьРекурсивно", Ложь);
	
	Возврат СтруктураНастроек;
	
КонецФункции

&НаСервере
Процедура ЗагрузитьНастройкиОбработки()
	
	Объект.ТипОперации                  = "ВвестиЗначения";
	Объект.ВариантЗаписиОбъекта         = "Записывать";
	
	Если Не КонтекстныйВызов Тогда
		ВидыИзменяемыхОбъектов = ЗагрузитьНастройкуВидовИзменяемыхОбъектов();
		Если Не ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
			ПредставлениеИзменяемыхОбъектов = ПредставлениеИзменяемыхОбъектов();
			ВыбранныеОбъектыВКонтексте.Очистить();
			ПерестроитьИнтерфейсФормыДляВыбранногоВидаОбъектов();
			Алгоритм = ПредставлениеИзменяемыхОбъектов;
		КонецЕсли;
	КонецЕсли;
	
	СтруктураНастроек = ХранилищеОбщихНастроекЗагрузить("Обработка.ГрупповоеИзменениеОбъектов", ВидыИзменяемыхОбъектов, СтруктураНастроек());
	Объект.ИзменятьВТранзакции = СтруктураНастроек.ИзменятьВТранзакции;
	Объект.ПрерыватьПриОшибке  = СтруктураНастроек.ПрерыватьПриОшибке;
	ОбрабатыватьРекурсивно     = СтруктураНастроек.ОбрабатыватьРекурсивно;
	Если ПравоДоступа("АдминистрированиеДанных", Метаданные) И СтруктураНастроек.Свойство("ПоказыватьСлужебныеРеквизиты") Тогда
		Объект.ПоказыватьСлужебныеРеквизиты = СтруктураНастроек.ПоказыватьСлужебныеРеквизиты;
	Иначе
		Объект.ПоказыватьСлужебныеРеквизиты = Ложь;
	КонецЕсли;
	
	ДоступноВыполнениеКода                    = ДоступноВыполнениеКода() И Не КонтекстныйВызов;
	Элементы.ПроизвольныйАлгоритм.Видимость   = ДоступноВыполнениеКода;
	Элементы.ГруппаТипОперации.Видимость      = ДоступноВыполнениеКода;

	ДоступноВыполнениеКодаВНебезопасномРежиме = ДоступноВыполнениеКодаВНебезопасномРежиме();
	Элементы.РежимВыполнения.Видимость        = ДоступноВыполнениеКодаВНебезопасномРежиме;
	
КонецПроцедуры

&НаСервере
Функция ЗагрузитьНастройкуВидовИзменяемыхОбъектов()
	
	ВидыИзменяемыхОбъектов = ХранилищеОбщихНастроекЗагрузить("ГрупповоеИзменениеОбъектов", "ВидыИзменяемыхОбъектов", "");
	
	СписокВидов = Новый Массив;
	Для Каждого ИмяОбъектаМетаданных Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяОбъектаМетаданных);
		Если ОбъектМетаданных <> Неопределено Тогда
			ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
			Если Элементы.ПредставлениеИзменяемыхОбъектов.СписокВыбора.НайтиПоЗначению(ПолноеИмя) <> Неопределено Тогда
				СписокВидов.Добавить(ПолноеИмя);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	ВидыИзменяемыхОбъектов = СтрСоединить(СписокВидов, ",");
	
	Возврат ВидыИзменяемыхОбъектов;
	
КонецФункции

// В модели сервиса, базовой конфигурации или без права АдминистраторСистемы нельзя выполнять произвольный алгоритм.
//
&НаСервереБезКонтекста
Функция ДоступноВыполнениеКодаВНебезопасномРежиме()
	Если ЭтоБазоваяВерсияКонфигурации()
		ИЛИ РазделениеВключено() Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если НЕ ПравоДоступа("Администрирование", Метаданные) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
КонецФункции

&НаСервереБезКонтекста
Функция ДоступноВыполнениеКода()
	
	Если РазделениеВключено() Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
КонецФункции

&НаСервереБезКонтекста
Функция ДоступныеПраваВыполнениеКода()
	
	Результат = Новый Структура();
	Результат.Вставить("ДоступноВыполнениеКодаВНебезопасномРежиме", ДоступноВыполнениеКодаВНебезопасномРежиме());
	Результат.Вставить("ДоступноВыполнениеКода", ДоступноВыполнениеКода());
	
	Возврат Результат;
КонецФункции

&НаКлиенте
Процедура РазрешитьРедактированиеРеквизитов()
	
	ВыбранныйРеквизит = ТекущийВыбранныйРеквизит;
	
	Если Не ПодсистемаСуществует("СтандартныеПодсистемы.ЗапретРедактированияРеквизитовОбъектов")
	 Или ОбщийМодуль("ЗапретРедактированияРеквизитовОбъектовКлиент") = Неопределено Тогда
		
		ВопросРазблокированияРеквизита(ВыбранныйРеквизит);
		Возврат;
	КонецЕсли;
	
	ЗаблокированныеРеквизиты = Новый Массив;
	ЗаблокированныеРеквизитыСтроки = РеквизитыОбъекта.НайтиСтроки(
		Новый Структура("ЗаблокированныйРеквизит", Истина));
	
	Для Каждого ОписаниеОперацииСтрока Из ЗаблокированныеРеквизитыСтроки Цикл
		ЗаблокированныеРеквизиты.Добавить(ОписаниеОперацииСтрока.Имя);
	КонецЦикла;
	
	МодульЗапретРедактированияРеквизитовОбъектовКлиент = ОбщийМодуль("ЗапретРедактированияРеквизитовОбъектовКлиент");
	
	ПараметрыПроцедуры = МодульЗапретРедактированияРеквизитовОбъектовКлиент.НовыеПараметрыРазрешитьРедактированиеРеквизитовОбъектов();
	ПараметрыПроцедуры.ОбработкаРезультата = Новый ОписаниеОповещения("ПриРазблокированииРеквизитов", ЭтотОбъект);
	ПараметрыПроцедуры.ПолноеИмяОбъекта = СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь)[0];
	ПараметрыПроцедуры.ЗаблокированныеРеквизиты = ЗаблокированныеРеквизиты;
	ПараметрыПроцедуры.ОтмеченныйРеквизит = ВыбранныйРеквизит.Имя;
	ПараметрыПроцедуры.АдресСсылокНаОбъекты = АдресМассиваИзменяемыхОбъектов();
	
	МодульЗапретРедактированияРеквизитовОбъектовКлиент.РазрешитьРедактированиеРеквизитовОбъектов(ПараметрыПроцедуры);
	
КонецПроцедуры

&НаКлиенте
Процедура ПерейтиНаСтраницуИзмененияОбъектов()
	
	Если Элементы.Страницы.ТекущаяСтраница = Элементы.НастройкаИзменений Тогда
		Элементы.Страницы.ТекущаяСтраница = Элементы.ИзменениеОбъектов;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура УстановитьКнопкиНаВремяИзменения(НачалоИзменения)
	
	ВыполняетсяОбработка = НачалоИзменения;

	Элементы.ФормаИзменить.Доступность = Истина;
	
	Если НачалоИзменения Тогда
		Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Прервать'");
	Иначе
		Если ОбъектыКоторыеНеУдалосьИзменить.Количество() > 0 Тогда
			Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Повторить изменение'");
		Иначе
			Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Закрыть'");
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ИзменитьОбъекты()
	
	ОчиститьСообщения();
	ТекущееСостояниеИзменения = Новый Структура;
	КоличествоОбъектовДляОбработки = КоличествоВыбранныхОбъектов(Истина, Истина);
	
	ПоказатьОповещениеПользователя(НСтр("ru = 'Изменение выделенных элементов'"), ,НСтр("ru = 'Пожалуйста подождите, обработка может занять некоторое время...'"));
	ПоказыватьПроцентОбработанных = Ложь;
	
	ТекущееСостояниеИзменения.Вставить("ЕстьЭлементыДляОбработки", Истина);
	
	// Позиция последнего обработанного элемента. 1 - первый элемент.
	ТекущееСостояниеИзменения.Вставить("ТекущаяПозиция", 0);
	
	// Деление на порции для многопоточного выполнения происходит в модуле объекта.
	ТекущееСостояниеИзменения.Вставить("РазмерПорции", КоличествоОбъектовДляОбработки);
	
	ТекущееСостояниеИзменения.Вставить("КоличествоОшибок", 0);            // Инициализируем счетчик ошибок.
	ТекущееСостояниеИзменения.Вставить("КоличествоИзмененных", 0);        // Инициализируем счетчик измененных.
	ТекущееСостояниеИзменения.Вставить("КоличествоОбъектовДляОбработки",  КоличествоОбъектовДляОбработки);
	ТекущееСостояниеИзменения.Вставить("ОстанавливатьИзменениеПриОшибке", Объект.ПрерыватьПриОшибке);
	ТекущееСостояниеИзменения.Вставить("ПоказыватьПроцентОбработанных",   ПоказыватьПроцентОбработанных);
	ТекущееСостояниеИзменения.Вставить("ПрерватьИзменение", Ложь);
	
	ПодключитьОбработчикОжидания("ИзменитьПорциюОбъектов", 0.1, Истина);
	
	Элементы.Страницы.ТекущаяСтраница = Элементы.ОжиданиеОбработки;
	
КонецПроцедуры

&НаКлиенте
Асинх Процедура ИзменитьПорциюОбъектов()
	
	Если ЗначениеЗаполнено(ПутьКФайлуВнешнейОбработкиНаКлиенте)
	   И Не ЗначениеЗаполнено(Объект.АдресДвоичныхДанныхВнешнейОбработки) Тогда
		
		Результат = Ждать ПоместитьФайлНаСерверАсинх(,,,
			ПутьКФайлуВнешнейОбработкиНаКлиенте, УникальныйИдентификатор);
		
		Если ТипЗнч(Результат) = Тип("ОписаниеПомещенногоФайла")
		   И Не Результат.ПомещениеФайлаОтменено Тогда
			Объект.АдресДвоичныхДанныхВнешнейОбработки = Результат.Адрес;
		КонецЕсли;
		
	КонецЕсли;
	
	ИзменитьНаСервере(ТекущееСостояниеИзменения.ОстанавливатьИзменениеПриОшибке);
	
	Если ДлительнаяОперация.Статус = "Выполнено" Тогда
		РезультатИзменения = ПолучитьИзВременногоХранилища(ДлительнаяОперация.АдресРезультата);
		Если ТипЗнч(РезультатИзменения) = Тип("Структура") Тогда
			ОбработатьРезультатИзменения(РезультатИзменения);
		Иначе
			ПриЗавершенииОперацииИзменения(ДлительнаяОперация, Неопределено);
		КонецЕсли;
	Иначе
		МодульДлительныеОперацииКлиент = ОбщийМодуль("ДлительныеОперацииКлиент");
		ПараметрыОжидания = МодульДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
		ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
		
		ОписаниеОповещения = Новый ОписаниеОповещения("ПриЗавершенииОперацииИзменения", ЭтотОбъект);
		МодульДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОписаниеОповещения, ПараметрыОжидания);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПриЗавершенииОперацииИзменения(Результат, ДополнительныеПараметры) Экспорт
	
	Если Результат = Неопределено Тогда
		НазадСервер();
		Возврат;
	КонецЕсли;
	
	Если Результат.Статус <> "Выполнено" Тогда
		НазадСервер();
		ВызватьИсключение Результат.КраткоеПредставлениеОшибки;
	КонецЕсли;
	
	РезультатыИзменений = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
	
	Если ТипЗнч(РезультатыИзменений) <> Тип("Соответствие") Тогда
		ТекстОшибки = НСтр("ru = 'Фоновое задание не вернуло результат'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	СтатусОшибка         = "Ошибка";
	
	Для Каждого РезультатИзменения Из РезультатыИзменений Цикл
		
		РезультатВыполненияПорции = РезультатИзменения.Значение;
		Если РезультатВыполненияПорции.Статус = СтатусОшибка Тогда
			ТекстОшибки = ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Фоновое задание потока завершилось с ошибкой:
				           |%1'"),
				РезультатВыполненияПорции.ПодробноеПредставлениеОшибки);
			ВызватьИсключение ТекстОшибки;
		Иначе
			
			РезультатИзмененияПорции = ПолучитьИзВременногоХранилища(РезультатВыполненияПорции.АдресРезультата);
			Если ТипЗнч(РезультатИзмененияПорции) <> Тип("Структура") Тогда
				ТекстОшибки = НСтр("ru = 'Фоновое задание потока не вернуло результат'");
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
		
			ОбработатьРезультатИзменения(РезультатИзмененияПорции);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры 

&НаКлиенте
Процедура ОбработатьРезультатИзменения(РезультатИзменения = Неопределено, ПродолжитьОбработку = Неопределено)
	Перем КоличествоОшибок, КоличествоИзмененных;
	
	Если ПродолжитьОбработку = Неопределено Тогда
		ПродолжитьОбработку = Истина;
	КонецЕсли;
	
	Пока ПродолжитьОбработку Цикл
		// Переносим информацию по обработанным объектам в таблицу.
		ЗаполнитьСостояниеОбработанных(РезультатИзменения, КоличествоОшибок, КоличествоИзмененных);
		
		ТекущееСостояниеИзменения.КоличествоОшибок = КоличествоОшибок + ТекущееСостояниеИзменения.КоличествоОшибок;
		ТекущееСостояниеИзменения.КоличествоИзмененных = КоличествоИзмененных + ТекущееСостояниеИзменения.КоличествоИзмененных;
		
		Если НЕ (ТекущееСостояниеИзменения.ОстанавливатьИзменениеПриОшибке И РезультатИзменения.ЕстьОшибки) Тогда
			Прервать;
		КонецЕсли;
		
		// При наличии ошибок в транзакции - откатываем всю транзакцию.
		Если Объект.ИзменятьВТранзакции Тогда
			ПодключитьОбработчикОжидания("ЗавершитьИзменениеОбъектов", 0.1, Истина);
			Возврат; // Досрочный выход из цикла и процедуры.
		КонецЕсли;
		
		ТекстВопроса = НСтр("ru = 'При изменении элементов (группы элементов) возникли ошибки.
			|Прервать изменение элементов и перейти к просмотру ошибок?'");
		Кнопки = Новый СписокЗначений;
		Кнопки.Добавить(КодВозвратаДиалога.Прервать, НСтр("ru = 'Прервать'"));
		Кнопки.Добавить(КодВозвратаДиалога.Пропустить, НСтр("ru = 'Продолжить'"));
		Кнопки.Добавить(КодВозвратаДиалога.Нет, НСтр("ru = 'Больше не спрашивать'"));
		
		ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьРезультатИзмененияОтветПолучен", ЭтотОбъект, РезультатИзменения);
		ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, Кнопки, , КодВозвратаДиалога.Прервать, НСтр("ru = 'Ошибки при изменении элементов'"));
		Возврат;
	КонецЦикла;
	
	ТекущееСостояниеИзменения.ТекущаяПозиция = ТекущееСостояниеИзменения.ТекущаяПозиция + РезультатИзменения.СостояниеОбработки.Количество();
	
	Если ТекущееСостояниеИзменения.ПоказыватьПроцентОбработанных Тогда
		// Вычисляем текущий процент обработанных объектов.
		ТекущийПроцент = Окр(ТекущееСостояниеИзменения.ТекущаяПозиция / ТекущееСостояниеИзменения.КоличествоОбъектовДляОбработки * 100);
		Состояние(НСтр("ru = 'Обрабатываются элементы...'"), ТекущийПроцент, НСтр("ru = 'Изменение выделенных элементов'"));
	КонецЕсли;
	
	ЕстьЭлементыДляОбработки = ?(ТекущееСостояниеИзменения.ТекущаяПозиция < ТекущееСостояниеИзменения.КоличествоОбъектовДляОбработки, Истина, Ложь);
	
	Если ЕстьЭлементыДляОбработки И НЕ ТекущееСостояниеИзменения.ПрерватьИзменение Тогда
		ПодключитьОбработчикОжидания("ИзменитьПорциюОбъектов", 0.1, Истина);
	Иначе
		ПодключитьОбработчикОжидания("ЗавершитьИзменениеОбъектов", 0.1, Истина);
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура ОбработатьРезультатИзмененияОтветПолучен(РезультатВопроса, РезультатИзменения) Экспорт
	
	Если РезультатВопроса = Неопределено Или РезультатВопроса = КодВозвратаДиалога.Прервать Тогда
		ПодключитьОбработчикОжидания("ЗавершитьИзменениеОбъектов", 0.1, Истина);
		Возврат;
	ИначеЕсли РезультатВопроса = КодВозвратаДиалога.Нет Тогда
		ТекущееСостояниеИзменения.ОстанавливатьИзменениеПриОшибке = Ложь;
	КонецЕсли;
	
	ОбработатьРезультатИзменения(РезультатИзменения, Ложь);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗавершитьИзменениеОбъектов()
	
	УстановитьКнопкиНаВремяИзменения(Ложь);
	ЗавершающиеДействияПриИзмененииСервер();
	
	Для Каждого Тип Из ТипыИзменяемыхОбъектов() Цикл
		ОповеститьОбИзменении(Тип);
	КонецЦикла;
	
	Оповестить("ЗавершениеГрупповогоИзмененияОбъектов");
	
	ОбработкаЗавершена = ТекущееСостояниеИзменения.КоличествоИзмененных = ТекущееСостояниеИзменения.КоличествоОбъектовДляОбработки;
	Если ОбработкаЗавершена Тогда
		ПоказатьОповещениеПользователя(НСтр("ru = 'Изменение реквизитов элементов'"), , 
			ПодставитьПараметрыВСтроку(НСтр("ru = 'Изменены элементы (%1).'"), ТекущееСостояниеИзменения.КоличествоИзмененных));
		ПерейтиНаСтраницуВсеГотово();
		Возврат;
	КонецЕсли;
	
	Элементы.ГруппаОбъектыКоторыеНеУдалосьИзменить.Видимость = ОбъектыКоторыеНеУдалосьИзменить.Количество() > 0;
	
	Если ОбработкаЗавершена Тогда
		ШаблонСообщения = НСтр("ru = 'Изменения выполнены во всех выбранных элементах (%2).'");
	Иначе
		Если Объект.ИзменятьВТранзакции Или ТекущееСостояниеИзменения.КоличествоИзмененных = 0 Тогда
			ШаблонСообщения = НСтр("ru = 'Изменения не выполнены.'");
		Иначе
			ШаблонСообщения = НСтр("ru = 'Изменения выполнены частично.
										|Изменено: %1; Не удалось изменить: %3'");
		КонецЕсли;
	КонецЕсли;
	
	Если Объект.ИзменятьВТранзакции И Не ОбработкаЗавершена Тогда
		КоличествоПропущенных = ТекущееСостояниеИзменения.КоличествоОбъектовДляОбработки - ТекущееСостояниеИзменения.КоличествоОшибок;
		Если КоличествоПропущенных > 0 И Не ТекущееСостояниеИзменения.ПрерватьИзменение Тогда
			СтрокаТаблицы = ОбъектыКоторыеНеУдалосьИзменить.Добавить();
			СтрокаТаблицы.Объект = ПодставитьПараметрыВСтроку(НСтр("ru = '... и другие элементы (%1)'"), КоличествоПропущенных);
			СтрокаТаблицы.Причина = НСтр("ru = 'Пропущены, так как не были изменены один или более элементов.'");
		КонецЕсли;
	КонецЕсли;
	
	Элементы.НадписьРезультатыОбработки.Заголовок = ПодставитьПараметрыВСтроку(
		ШаблонСообщения,
		ТекущееСостояниеИзменения.КоличествоИзмененных,
		ТекущееСостояниеИзменения.КоличествоОбъектовДляОбработки,
		ТекущееСостояниеИзменения.КоличествоОшибок);
		
	Элементы.ФормаНазад.Видимость = Истина;
	
КонецПроцедуры

&НаСервере
Процедура НазадСервер()
	
	Элементы.Страницы.ТекущаяСтраница = Элементы.НастройкаИзменений;
	
	ОбработкаЗавершена = Ложь;
	ОбъектыКоторыеНеУдалосьИзменить.Очистить();
	Элементы.ФормаНазад.Видимость = Ложь;
	Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
		Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Выполнить'");
		Элементы.ФормаИзменить.РасширеннаяПодсказка.Заголовок = НСтр("ru = 'Выполнить алгоритм'");
	Иначе
		Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Изменить реквизиты'");
	КонецЕсли;
	
	ОбновитьНадписиСервер();
	
КонецПроцедуры

&НаСервере
Процедура ПерейтиНаСтраницуВсеГотово()
	
	Элементы.Страницы.ТекущаяСтраница = Элементы.ВсеГотово;
	Элементы.НадписьУспешноЗавершено.Заголовок = ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Реквизиты выбранных элементов были изменены.
			|Всего изменено элементов: %1'"), ТекущееСостояниеИзменения.КоличествоИзмененных);
	Элементы.ФормаИзменить.Заголовок = НСтр("ru = 'Готово'");
	Элементы.ФормаНазад.Видимость = Истина;
	
	ДобавитьСообщениеИзменениеРеквизитовМожноВыполнятьБыстрее();
	
КонецПроцедуры

// Сообщение о том, что изменение реквизитов можно выполнять быстрее, выводится, если:
// 1. Режим работы клиент-сервер и не модель сервиса.
// 2. Установлен флаг выполнения в транзакции.
// 3. Установленное кол-во порций в настройках администрирования более 1.
//
&НаСервере
Процедура ДобавитьСообщениеИзменениеРеквизитовМожноВыполнятьБыстрее()
	
	Если Не Объект.ИзменятьВТранзакции Тогда
		Возврат;
	КонецЕсли;
	
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	Если Не ОбработкаОбъект.ДоступныДлительныеОперации() Тогда
		Возврат;
	КонецЕсли;
	
	МодульДлительныеОперации = ОбщийМодуль("ДлительныеОперации");
	
	КоличествоПотоковДлительныхОпераций = МодульДлительныеОперации.ДопустимоеКоличествоПотоков();
	Если КоличествоПотоковДлительныхОпераций <= 1 Тогда
		Возврат;
	КонецЕсли;
	
	Элементы.НадписьУспешноЗавершено.Заголовок = Элементы.НадписьУспешноЗавершено.Заголовок
		+ Символы.ПС + Символы.ПС
		+ НСтр("ru = 'Изменение реквизитов можно выполнять быстрее.
		|Для этого нужно снять флаг ""Изменять в транзакции"" в дополнительных параметрах.'");
	
КонецПроцедуры

&НаСервере
Функция ТипыИзменяемыхОбъектов()
	Результат = Новый Массив;
	Для Каждого ВидОбъектов Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		МенеджерОбъекта = МенеджерОбъектаПоПолномуИмени(ВидОбъектов);
		Результат.Добавить(ТипЗнч(МенеджерОбъекта.ПустаяСсылка()));
	КонецЦикла;
	Возврат Результат;
КонецФункции

&НаСервере
Процедура ЗавершающиеДействияПриИзмененииСервер()
	Если ДлительнаяОперация.Свойство("ИдентификаторЗадания") Тогда
		МодульДлительныеОперации = ОбщийМодуль("ДлительныеОперации");
		МодульДлительныеОперации.ОтменитьВыполнениеЗадания(ДлительнаяОперация.ИдентификаторЗадания);
	КонецЕсли;
	
	Элементы.Страницы.ТекущаяСтраница = Элементы.ИзменениеОбъектов;
	СохранитьТекущиеНастройкиИзменения();
КонецПроцедуры

&НаСервере
Процедура СохранитьТекущиеНастройкиИзменения()
	
	ТекущиеНастройки = ТекущиеНастройкиИзменения();
	Если ТекущиеНастройки <> Неопределено Тогда
		ДобавитьИзменениеВИсторию(ТекущиеНастройки.ОписаниеИзменения, ТекущиеНастройки.ПредставлениеИзменения);
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция ТекущиеНастройкиИзменения()
	
	Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
		Результат = Новый Структура;
		Результат.Вставить("ОписаниеИзменения", КодАлгоритма);
		Результат.Вставить("ПредставлениеИзменения", Алгоритм);
		Возврат Результат;
	КонецЕсли;
	
	ОписаниеИзменения = Новый Структура;
	КоллекцияОпераций = РеквизитыОбъекта.НайтиСтроки(Новый Структура("Изменять", Истина));
	
	ШаблонПредставления = "[Поле] = <Значение>";
	ПредставлениеИзменения = "";
	
	НастройкаИзмененияРеквизитов = Новый Массив;
	Для Каждого ОписаниеОперации Из КоллекцияОпераций Цикл
		СтруктураИзменения = Новый Структура;
		СтруктураИзменения.Вставить("ВидОперации", ОписаниеОперации.ВидОперации);
		СтруктураИзменения.Вставить("ИмяРеквизита", ОписаниеОперации.Имя);
		СтруктураИзменения.Вставить("Свойство", ОписаниеОперации.Свойство);
		СтруктураИзменения.Вставить("Значение", ОписаниеОперации.Значение);
		НастройкаИзмененияРеквизитов.Добавить(СтруктураИзменения);
		
		ЗначениеСтрокой = СокрЛП(Строка(ОписаниеОперации.Значение));
		Если ПустаяСтрока(ЗначениеСтрокой) Тогда
			ЗначениеСтрокой = """""";
		КонецЕсли;
		Изменение = СтрЗаменить(ШаблонПредставления, "[Поле]", СокрЛП(Строка(ОписаниеОперации.Представление)));
		Изменение = СтрЗаменить(Изменение, "<Значение>", ЗначениеСтрокой);
		
		Если Не ПустаяСтрока(ПредставлениеИзменения) Тогда
			ПредставлениеИзменения = ПредставлениеИзменения + "; ";
		КонецЕсли;
		ПредставлениеИзменения = ПредставлениеИзменения + Изменение;
	КонецЦикла;
	ОписаниеИзменения.Вставить("Реквизиты", НастройкаИзмененияРеквизитов);
	
	НастройкаИзмененияТабличныхЧастей = Новый Структура;
	Для Каждого ТабличнаяЧасть Из ИзменяемыеТабличныеЧасти() Цикл
		Если Не ПустаяСтрока(ПредставлениеИзменения) Тогда
			ПредставлениеИзменения = ПредставлениеИзменения + "; ";
		КонецЕсли;
		ПредставлениеИзменения = ПредставлениеИзменения + ТабличнаяЧасть.Ключ + " (";
		НастройкаИзмененияРеквизитов = Новый Массив;
		СтрокаРеквизитов = "";
		Для Каждого Реквизит Из ТабличнаяЧасть.Значение Цикл
			СтруктураИзменения = Новый Структура("Имя,Значение");
			ЗаполнитьЗначенияСвойств(СтруктураИзменения, Реквизит);
			НастройкаИзмененияРеквизитов.Добавить(СтруктураИзменения);
			
			Изменение = СтрЗаменить(ШаблонПредставления, "[Поле]", СокрЛП(Строка(Реквизит.Представление)));
			Изменение = СтрЗаменить(Изменение, "<Значение>", СокрЛП(Строка(Реквизит.Значение)));
			
			Если Не ПустаяСтрока(СтрокаРеквизитов) Тогда
				СтрокаРеквизитов = СтрокаРеквизитов + "; ";
			КонецЕсли;
			СтрокаРеквизитов = СтрокаРеквизитов + Изменение;
		КонецЦикла;
		ПредставлениеИзменения = ПредставлениеИзменения + СтрокаРеквизитов + ")";
		НастройкаИзмененияТабличныхЧастей.Вставить(ТабличнаяЧасть.Ключ, НастройкаИзмененияРеквизитов);
	КонецЦикла;
	
	ОписаниеИзменения.Вставить("ТабличныеЧасти", НастройкаИзмененияТабличныхЧастей);
	
	Результат = Неопределено;
	Если ЗначениеЗаполнено(ПредставлениеИзменения) Тогда
		Результат = Новый Структура;
		Результат.Вставить("ОписаниеИзменения", ОписаниеИзменения);
		Результат.Вставить("ПредставлениеИзменения", ПредставлениеИзменения);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

&НаКлиенте
Процедура ЗаполнитьСостояниеОбработанных(РезультатИзменения, КоличествоОшибок, КоличествоИзмененных)
	
	КоличествоОшибок = 0;
	КоличествоИзмененных = 0;
	
	Для Каждого СостояниеОбработанногоОбъекта Из РезультатИзменения.СостояниеОбработки Цикл
		Если Не ПустаяСтрока(СостояниеОбработанногоОбъекта.Значение.КодОшибки) Тогда
			КоличествоОшибок = КоличествоОшибок + 1;
			
			ЗаписьОбОшибке = ОбъектыКоторыеНеУдалосьИзменить.Добавить();
			ЗаписьОбОшибке.Объект = СостояниеОбработанногоОбъекта.Ключ;
			ЗаписьОбОшибке.Причина = СостояниеОбработанногоОбъекта.Значение.СообщениеОбОшибке;
		Иначе
			КоличествоИзмененных = КоличествоИзмененных + 1;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Функция СледующаяПорцияОбъектовДляИзменения()
	
	НачалоВыборки = ТекущееСостояниеИзменения.ТекущаяПозиция;
	КонецВыборки = ТекущееСостояниеИзменения.ТекущаяПозиция + ТекущееСостояниеИзменения.РазмерПорции - 1;
	
	ВыбранныеОбъекты = ВыбранныеОбъекты();
	Если КонецВыборки > ВыбранныеОбъекты.Строки.Количество() - 1 Тогда
		КонецВыборки = ВыбранныеОбъекты.Строки.Количество() - 1;
	КонецЕсли;
	
	Результат = Новый ДеревоЗначений;
	Для Каждого Колонка Из ВыбранныеОбъекты.Колонки Цикл
		Результат.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
	КонецЦикла;
	
	Для Индекс = НачалоВыборки По КонецВыборки Цикл
		ОписаниеОбъекта = Результат.Строки.Добавить();
		ЗаполнитьЗначенияСвойств(ОписаниеОбъекта, ВыбранныеОбъекты.Строки[Индекс]);
		Для Каждого СтрокаОбъекта Из ВыбранныеОбъекты.Строки[Индекс].Строки Цикл
			ЗаполнитьЗначенияСвойств(ОписаниеОбъекта.Строки.Добавить(), СтрокаОбъекта);
		КонецЦикла;
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Функция ИзменяемыеРеквизиты(ИмяТабличнойЧасти = "РеквизитыОбъекта")
	ТаблицаРеквизитов = ЭтотОбъект[ИмяТабличнойЧасти];
	Возврат ТаблицаЗначенийВМассив(ТаблицаРеквизитов.Выгрузить(Новый Структура("Изменять", Истина)));
КонецФункции

&НаСервере
Функция ИзменяемыеТабличныеЧасти()
	Результат = Новый Структура;
	Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
		ИзменяемыеРеквизиты = ИзменяемыеРеквизиты(ТабличнаяЧасть.Значение);
		Если ИзменяемыеРеквизиты.Количество() > 0 Тогда
			ИмяТабличнойЧасти = Сред(ТабличнаяЧасть.Значение, СтрДлина("ТабличнаяЧасть") + 1);
			Результат.Вставить(ИмяТабличнойЧасти, ИзменяемыеРеквизиты);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

&НаСервере
Процедура ИзменитьНаСервере(Знач ОстанавливатьИзменениеПриОшибке)
	
	ОбъектыДляОбработки = СледующаяПорцияОбъектовДляИзменения();
	
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	
	ПараметрыЗадания = Новый Структура;
	ПараметрыЗадания.Вставить("ОбрабатываемыеОбъекты", Новый ХранилищеЗначения(ОбъектыДляОбработки));
	ПараметрыЗадания.Вставить("ОстанавливатьИзменениеПриОшибке", ОстанавливатьИзменениеПриОшибке);
	ПараметрыЗадания.Вставить("ИзменятьВТранзакции", ОбработкаОбъект.ИзменятьВТранзакции);
	ПараметрыЗадания.Вставить("ПрерыватьПриОшибке", ОбработкаОбъект.ПрерыватьПриОшибке);
	ПараметрыЗадания.Вставить("ТипОперации", ОбработкаОбъект.ТипОперации);
	ПараметрыЗадания.Вставить("КодАлгоритма", КодАлгоритма);
	ПараметрыЗадания.Вставить("РежимВыполнения", ОбработкаОбъект.РежимВыполнения);
	ПараметрыЗадания.Вставить("ВариантЗаписиОбъекта", ОбработкаОбъект.ВариантЗаписиОбъекта);
	ПараметрыЗадания.Вставить("ИспользуютсяДопРеквизиты", ОбработкаОбъект.ИспользуютсяДопРеквизиты);
	ПараметрыЗадания.Вставить("ИспользуютсяДопСведения", ОбработкаОбъект.ИспользуютсяДопСведения);
	ПараметрыЗадания.Вставить("ИзменяемыеРеквизиты", ИзменяемыеРеквизиты());
	ПараметрыЗадания.Вставить("ДоступныеРеквизиты", ТаблицаЗначенийВМассив(РеквизитыОбъекта.Выгрузить(, "Имя,Представление,ВидОперации,Свойство")));
	ПараметрыЗадания.Вставить("ИзменяемыеТабличныеЧасти", ИзменяемыеТабличныеЧасти());
	ПараметрыЗадания.Вставить("ОбъектыДляИзменения", Новый ХранилищеЗначения(ВыбранныеОбъекты()));
	ПараметрыЗадания.Вставить("РежимРазработчика", ОбработкаОбъект.РежимРазработчика);
	ПараметрыЗадания.Вставить("ВнешнийОтчетОбработка", Неопределено);
	
	АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
	ДлительнаяОперация = ОбработкаОбъект.ИзменитьОбъекты(ПараметрыЗадания, АдресХранилища);
	
	Если ДлительнаяОперация = Неопределено Тогда
		ДлительнаяОперация = Новый Структура("Статус, АдресРезультата");
		ДлительнаяОперация.Статус          = "Выполнено";
		ДлительнаяОперация.АдресРезультата = АдресХранилища;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция АдресМассиваИзменяемыхОбъектов()
	
	ВыбранныеОбъекты = ВыбранныеОбъекты();
	Ссылки = ВыбранныеОбъекты.Строки.ВыгрузитьКолонку("Ссылка");
	
	Возврат ПоместитьВоВременноеХранилище(Ссылки, УникальныйИдентификатор);
	
КонецФункции

&НаСервереБезКонтекста
Функция ОбъектМетаданныхИерархический(СсылкаПервого)
	
	ВидОбъектаПоСсылке = ВидОбъектаПоСсылке(СсылкаПервого);
	
	Если ((ВидОбъектаПоСсылке = "Справочник" ИЛИ ВидОбъектаПоСсылке = "ПланВидовХарактеристик") И СсылкаПервого.Метаданные().Иерархический)
	 ИЛИ (ВидОбъектаПоСсылке = "ПланСчетов") Тогда
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

&НаСервереБезКонтекста
Функция ИерархияГруппИЭлементов(СсылкаПервого)
	
	ВидОбъектаПоСсылке = ВидОбъектаПоСсылке(СсылкаПервого);
	
	Возврат (ВидОбъектаПоСсылке = "Справочник" И СсылкаПервого.Метаданные().Иерархический
		И СсылкаПервого.Метаданные().ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов)
		Или (ВидОбъектаПоСсылке = "ПланВидовХарактеристик" И СсылкаПервого.Метаданные().Иерархический);
	
КонецФункции

&НаКлиенте
Процедура СброситьНастройкиИзменения()
	Для Каждого Реквизит Из РеквизитыОбъекта Цикл
		Реквизит.Значение = Неопределено;
		Реквизит.Изменять = Ложь;
	КонецЦикла;
	
	Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
		Для Каждого Реквизит Из ЭтотОбъект[ТабличнаяЧасть.Значение] Цикл
			Реквизит.Значение = Неопределено;
			Реквизит.Изменять = Ложь;
		КонецЦикла;
	КонецЦикла;	
КонецПроцедуры

&НаКлиенте
Процедура НастройкаОтбораНажатие(Элемент)
	ПерейтиКНастройкеОтбора();
КонецПроцедуры

&НаКлиенте
Процедура ПриЗакрытииФормыВыбранныхОбъектов(Настройки, ДополнительныеПараметры) Экспорт
	Если ТипЗнч(Настройки) = Тип("НастройкиКомпоновкиДанных") Тогда
		КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
		ОбновитьНадписи();
		ОчиститьВременноеХранилищеСпискаВыбранных(АдресСпискаВыбранных);
	КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция НастройкиОтбора()
	Результат = Новый Структура;
	Результат.Вставить("ОбновитьСписок", Ложь);
	Результат.Вставить("ВключитьТабличныеЧастиВВыборку", Ложь);
	Результат.Вставить("ОграничитьВыборку", Ложь);
	Возврат Результат;
КонецФункции

// Параметры:
//   НастройкиОтбора - Неопределено
//                   - Структура:
//   * ОграничитьВыборку - Булево
//   * ВключитьТабличныеЧастиВВыборку - Булево
//   * ОбновитьСписок - Булево
//   ТекстСообщенияОбОшибке - Строка
//
// Возвращаемое значение:
//   ДеревоЗначений:
//   * Ссылка - ЛюбаяСсылка
//
&НаСервере
Функция ВыбранныеОбъекты(НастройкиОтбора = Неопределено, ТекстСообщенияОбОшибке = "")
	
	Если НастройкиОтбора = Неопределено Тогда
		НастройкиОтбора = НастройкиОтбора();
	КонецЕсли;
	
	ОбновитьСписок = НастройкиОтбора.ОбновитьСписок;
	ВключитьТабличныеЧастиВВыборку = НастройкиОтбора.ВключитьТабличныеЧастиВВыборку;
	ОграничитьВыборку = НастройкиОтбора.ОграничитьВыборку;
	
	Если Не ОбновитьСписок И Не ОграничитьВыборку И Не ПустаяСтрока(АдресСпискаВыбранных) Тогда
		Возврат ПолучитьИзВременногоХранилища(АдресСпискаВыбранных);
	КонецЕсли;
		
	Результат = Новый ДеревоЗначений;
	
	Если Не ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
		ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
		ТекстЗапроса = ОбработкаОбъект.ТекстЗапроса(ВидыИзменяемыхОбъектов, ОграничитьВыборку);
		СхемаКомпоновкиДанных = СхемаКомпоновкиДанных(ТекстЗапроса);
		
		КомпоновщикНастроекКомпоновкиДанных = Новый КомпоновщикНастроекКомпоновкиДанных;
		АдресСхемы = ПоместитьВоВременноеХранилище(СхемаКомпоновкиДанных, УникальныйИдентификатор);
		КомпоновщикНастроекКомпоновкиДанных.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы));
		КомпоновщикНастроекКомпоновкиДанных.ЗагрузитьНастройки(КомпоновщикНастроек.Настройки);
		Если ВключитьТабличныеЧастиВВыборку Тогда
			УстановитьНастройкуСтруктурыВыводаРезультата(КомпоновщикНастроекКомпоновкиДанных.Настройки, ВключитьТабличныеЧастиВВыборку);
		КонецЕсли;
		
		Если ОбъектыКоторыеНеУдалосьИзменить.Количество() > 0 И Не Объект.ИзменятьВТранзакции Тогда // повтор для неизмененных
			ЭлементОтбора = КомпоновщикНастроекКомпоновкиДанных.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
			ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
			ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
			ЭлементОтбора.ПравоеЗначение = Новый СписокЗначений;
			ЭлементОтбора.ПравоеЗначение.ЗагрузитьЗначения(ОбъектыКоторыеНеУдалосьИзменить.Выгрузить().ВыгрузитьКолонку("Объект"));
		КонецЕсли;
		
		Результат = Новый ДеревоЗначений;
		КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
		Попытка
			МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных,
				КомпоновщикНастроекКомпоновкиДанных.Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
		Исключение
			ТекстСообщенияОбОшибке = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
			Возврат Результат;
		КонецПопытки;
			
		ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
		ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);

		ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
		ПроцессорВывода.УстановитьОбъект(Результат);
		ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
		Если Не ОграничитьВыборку Тогда
			АдресСпискаВыбранных = ПоместитьВоВременноеХранилище(Результат, УникальныйИдентификатор);
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

&НаСервереБезКонтекста
Процедура ОчиститьВременноеХранилищеСпискаВыбранных(АдресСпискаВыбранных)
	
	Если ЗначениеЗаполнено(АдресСпискаВыбранных) Тогда
		УдалитьИзВременногоХранилища(АдресСпискаВыбранных);
		АдресСпискаВыбранных = "";
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура УстановитьНастройкуСтруктурыВыводаРезультата(Настройки, ДляИзменения = Ложь)
	
	Настройки.Структура.Очистить();
	Настройки.Выбор.Элементы.Очистить();
	
	ГруппировкаКомпоновкиДанных = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
	ГруппировкаКомпоновкиДанных.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
	ГруппировкаКомпоновкиДанных.Использование = Истина;
	
	ПолеГруппировки = ГруппировкаКомпоновкиДанных.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
	ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных("Ссылка");
	ПолеГруппировки.Использование = Истина;
	
	ПолеВыбора = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
	ПолеВыбора.Поле = Новый ПолеКомпоновкиДанных("Ссылка");
	ПолеВыбора.Использование = Истина;
	
	Если ДляИзменения Тогда
		ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
		ОбщиеРеквизитыОбъектов = ОбработкаОбъект.ОбщиеРеквизитыОбъектов(ВидыИзменяемыхОбъектов);
		Для Каждого ТабличнаяЧасть Из ОбщиеРеквизитыОбъектов.ТабличныеЧасти Цикл
			ИмяТабличнойЧасти = ТабличнаяЧасть.Ключ;
			
			ГруппировкаТаблицы = ГруппировкаКомпоновкиДанных.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
			ГруппировкаТаблицы.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
			ГруппировкаТаблицы.Использование = Истина;
			
			ПолеГруппировки = ГруппировкаТаблицы.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
			ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных(ИмяТабличнойЧасти + ".НомерСтроки");
			ПолеГруппировки.Использование = Истина;
			
			ПолеВыбора = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
			ПолеВыбора.Поле = Новый ПолеКомпоновкиДанных(ИмяТабличнойЧасти + ".НомерСтроки");
			ПолеВыбора.Использование = Истина;
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция КоличествоВыбранныхОбъектов(Пересчитать = Ложь, ДляИзменения = Ложь, ТекстСообщенияОбОшибке = "")
	НастройкиОтбора = НастройкиОтбора();
	НастройкиОтбора.ОбновитьСписок = Пересчитать;
	НастройкиОтбора.ВключитьТабличныеЧастиВВыборку = ДляИзменения;
	
	Возврат ВыбранныеОбъекты(НастройкиОтбора, ТекстСообщенияОбОшибке).Строки.Количество();
КонецФункции

&НаСервере
Функция СхемаКомпоновкиДанных(ТекстЗапроса)
	
	СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
	
	ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить();
	ИсточникДанных.Имя = "ИсточникДанных1";
	ИсточникДанных.ТипИсточникаДанных = "local";
	
	НаборДанных = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
	НаборДанных.ИсточникДанных = "ИсточникДанных1";
	НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
	НаборДанных.Запрос = ТекстЗапроса;
	НаборДанных.Имя = "НаборДанных1";
	
	Возврат СхемаКомпоновкиДанных;
	
КонецФункции

&НаКлиенте
Процедура ВидИзменяемыхОбъектовВыборСделан(Знач ВыбранныеОбъекты, ДополнительныеПараметры) Экспорт
	Если ВыбранныеОбъекты <> Неопределено И ВидыИзменяемыхОбъектов <> ВыбранныеОбъекты Тогда
		ВидыИзменяемыхОбъектов = СтрСоединить(ВыбранныеОбъекты, ",");
		ВыбранныеОбъектыВКонтексте.Очистить();
		ПерестроитьИнтерфейсФормыДляВыбранногоВидаОбъектов();
		Элементы.РеквизитыОбъектаАлгоритм.ОтборСтрок = Новый ФиксированнаяСтруктура(Новый Структура("ВидОперации", "1"));
		Если Не КонтекстныйВызов Тогда
			СохранитьВидыИзменяемыхОбъектов(ВидыИзменяемыхОбъектов, АдресСпискаВыбранных);
		КонецЕсли;	
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ПерестроитьИнтерфейсФормыДляВыбранногоВидаОбъектов()
	ИнициализироватьНастройкиФормы();
	ОбновитьВидимостьЭлементов();
	СформироватьПояснениеОНастроенныхИзменениях();
КонецПроцедуры

&НаСервере
Процедура ИнициализироватьНастройкиФормы()
	ИнициализироватьКомпоновщикНастроек();
	ЗагрузитьМетаданныеОбъекта();
	ЗагрузитьИсториюОпераций();
	ЗаполнитьПодменюРанееИзмененныеРеквизиты();
	ПредставлениеИзменяемыхОбъектов = ПредставлениеИзменяемыхОбъектов();
	ОбновитьНадписиСервер();
КонецПроцедуры

&НаСервере
Функция ПредставлениеИзменяемыхОбъектов()
	ПредставленияТипов = Новый Массив;
	Для Каждого ИмяОбъектаМетаданных Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяОбъектаМетаданных);
		ПредставленияТипов.Добавить(ОбъектМетаданных.Представление());
	КонецЦикла;
		
	Результат = СтрСоединить(ПредставленияТипов, ", ");
	Возврат Результат;
КонецФункции

&НаСервере
Процедура ИнициализироватьКомпоновщикНастроек()
	Если ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
		Возврат;
	КонецЕсли;
	
	ОбъектОбработка = РеквизитФормыВЗначение("Объект");
	ТекстЗапроса = ОбъектОбработка.ТекстЗапроса(ВидыИзменяемыхОбъектов);
	СхемаКомпоновкиДанных = СхемаКомпоновкиДанных(ТекстЗапроса);
	КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ПоместитьВоВременноеХранилище(СхемаКомпоновкиДанных, УникальныйИдентификатор)));
	КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
	
	Если ВыбранныеОбъектыВКонтексте.Количество() > 0 Тогда
		Если Параметры.Свойство("КомпоновщикНастроек") И ТипЗнч(Параметры.КомпоновщикНастроек) = Тип("КомпоновщикНастроекКомпоновкиДанных") Тогда
			НастройкиКомпоновщика = Параметры.КомпоновщикНастроек.ПолучитьНастройки();
			КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиКомпоновщика);
			КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.Очистить();
			
			УдаляемыеЭлементы = Новый Массив;
			Для Каждого Элемент Из КомпоновщикНастроек.Настройки.Порядок.Элементы Цикл
				ДоступноеПоле = КомпоновщикНастроек.Настройки.Порядок.ДоступныеПоляПорядка.НайтиПоле(Элемент.Поле);
				Если ДоступноеПоле = Неопределено Тогда
					УдаляемыеЭлементы.Добавить(Элемент);
				КонецЕсли;
			КонецЦикла;
			Для Каждого Элемент Из УдаляемыеЭлементы Цикл
				КомпоновщикНастроек.Настройки.Порядок.Элементы.Удалить(Элемент);
			КонецЦикла;
			
			КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
			Попытка
				КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки,,, 
					Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
			Исключение
				КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
			КонецПопытки;
		КонецЕсли;
		
		ЭлементОтбора = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
		Если УчитыватьИерархию И ОбрабатыватьРекурсивно Тогда
			ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии;
		Иначе
			ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
		КонецЕсли;
		ЭлементОтбора.ПравоеЗначение = Новый СписокЗначений;
		ЭлементОтбора.ПравоеЗначение.ЗагрузитьЗначения(ВыбранныеОбъектыВКонтексте.ВыгрузитьЗначения());
	
	КонецЕсли;
	
	УстановитьНастройкуСтруктурыВыводаРезультата(КомпоновщикНастроек.Настройки);
	
КонецПроцедуры

&НаСервере
Процедура ОчиститьСведенияОбОбъекте()
	УдаляемыеРеквизитыФормы = Новый Массив;
	Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
		УдаляемыеРеквизитыФормы.Добавить(ТабличнаяЧасть.Значение);
		Элементы.Удалить(Элементы.Найти("Страница" + ТабличнаяЧасть.Значение));
	КонецЦикла;
	ИзменитьРеквизиты(, УдаляемыеРеквизитыФормы);
	ТабличныеЧастиОбъекта.Очистить();
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьМетаданныеОбъекта(СохранитьТекущиеНастройкиИзменения = Ложь, СохраненныеНастройки = Неопределено)
	
	Если СохранитьТекущиеНастройкиИзменения Тогда
		ТекущиеНастройки =  ТекущиеНастройкиИзменения();
		Если ТекущиеНастройки <> Неопределено Тогда
			СохраненныеНастройки = ТекущиеНастройки.ОписаниеИзменения;
		КонецЕсли;
	КонецЕсли;
	
	ОчиститьСведенияОбОбъекте();
	
	ЗаблокированныеРеквизиты = ЗаблокированныеРеквизиты();
	НередактируемыеРеквизиты = НередактируемыеРеквизиты();
	ФильтруемыеРеквизиты = ФильтруемыеРеквизиты();
	
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	ОбщиеРеквизитыОбъектов = ОбработкаОбъект.ОбщиеРеквизитыОбъектов(ВидыИзменяемыхОбъектов);
	
	ЗаполнитьРеквизитыОбъекта(ЗаблокированныеРеквизиты, НередактируемыеРеквизиты, ФильтруемыеРеквизиты, ОбщиеРеквизитыОбъектов.Реквизиты);
	ЗаполнитьТабличныеЧастиОбъектов(ЗаблокированныеРеквизиты, НередактируемыеРеквизиты, ФильтруемыеРеквизиты, ОбщиеРеквизитыОбъектов.ТабличныеЧасти);
	
	СформироватьПояснениеПоАвтонумерации();
	УстановитьУсловноеОформление();
КонецПроцедуры

&НаСервере
Процедура СформироватьПояснениеПоАвтонумерации()
	
	Автонумерация = Неопределено;
	Для Каждого ИмяТипа Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяТипа); // ОбъектМетаданныхСправочник, ОбъектМетаданныхДокумент
		
		Если Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных) 
			Или Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных)
			Или Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных) Тогда
				Автонумерация = Неопределено;
				Прервать;
		КонецЕсли;
		
		Если Автонумерация = Неопределено Тогда
			Автонумерация = ОбъектМетаданных.Автонумерация;
			Продолжить;
		КонецЕсли;
		
		Если Автонумерация И Не ОбъектМетаданных.Автонумерация Тогда
			Автонумерация = Неопределено;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Если Автонумерация = Неопределено Тогда
		ПояснениеПоАвтонумерации = "";
	ИначеЕсли Автонумерация Тогда
		ПояснениеПоАвтонумерации = НСтр("ru = '<Установить автоматически>'");
	Иначе
		ПояснениеПоАвтонумерации = НСтр("ru = '<Очистить>'");
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция БлокируемыеРеквизитыОбъекта(ИмяОбъекта)
	
	Если ПодсистемаСуществует("СтандартныеПодсистемы.ЗапретРедактированияРеквизитовОбъектов") Тогда
		МодульЗапретРедактированияРеквизитовОбъектов = ОбщийМодуль("ЗапретРедактированияРеквизитовОбъектов");
		Возврат МодульЗапретРедактированияРеквизитовОбъектов.БлокируемыеРеквизитыОбъекта(ИмяОбъекта);
	КонецЕсли;
	
	Возврат Новый Массив;
	
КонецФункции

&НаСервере
Функция ЗаблокированныеРеквизиты()
	
	Результат = Новый Массив;
	
	Для Каждого ВидОбъектов Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		Если ВерсияБСПСоответствуетТребованиям() Тогда
			Для Каждого Реквизит Из БлокируемыеРеквизитыОбъекта(ВидОбъектов) Цикл
				Если Результат.Найти(Реквизит) = Неопределено Тогда
					Результат.Добавить(Реквизит);
				КонецЕсли;
			КонецЦикла;
			Продолжить;
		КонецЕсли;
		
		// В конфигурациях без БСП или на старых версиях БСП, пытаемся определить, 
		// есть ли у объекта блокируемые реквизиты (подсистема "Запрет редактирования реквизитов объектов").
		МенеджерОбъекта = МенеджерОбъектаПоПолномуИмени(ВидОбъектов);
		Попытка
			БлокируемыеРеквизитыОписание = МенеджерОбъекта.ПолучитьБлокируемыеРеквизитыОбъекта();
		Исключение
			// метод не найден
			БлокируемыеРеквизитыОписание = Неопределено;
		КонецПопытки;
	
		Если БлокируемыеРеквизитыОписание <> Неопределено Тогда
			Для Каждого БлокируемыйРеквизитОписание Из БлокируемыеРеквизитыОписание Цикл
				ИмяРеквизита = СокрЛП(СтрРазделить(БлокируемыйРеквизитОписание, ";")[0]);
				Если Результат.Найти(ИмяРеквизита) = Неопределено Тогда
					Результат.Добавить(ИмяРеквизита);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Функция НередактируемыеРеквизиты()
	
	Если Объект.ПоказыватьСлужебныеРеквизиты Тогда
		Возврат Новый Массив;
	КонецЕсли;
	
	Результат = Новый Массив;
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	
	ИменаРеквизитов = Новый Соответствие;
	
	Для Каждого ВидИзменяемыхОбъектов Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ВидИзменяемыхОбъектов);
		НастройкиРедактированияРеквизитов = ОбработкаОбъект.НастройкиРедактированияРеквизитов(ОбъектМетаданных);
		Редактируемые = НастройкиРедактированияРеквизитов.Редактируемые;
		НеРедактируемые = НастройкиРедактированияРеквизитов.НеРедактируемые;
		
		Если ЗначениеЗаполнено(НеРедактируемые) Тогда
			Если НеРедактируемые.Найти("*") = Неопределено Тогда
				Для Каждого ИмяРеквизита Из НеРедактируемые Цикл
					ИменаРеквизитов.Вставить(ИмяРеквизита);
				КонецЦикла;
				Продолжить;
			Иначе
				Редактируемые = Новый Массив;
			КонецЕсли;
		Иначе
			Если Редактируемые = Неопределено Или ТипЗнч(Редактируемые) = Тип("Массив") И Редактируемые.Найти("*") <> Неопределено Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		
		НеРедактируемые = Новый Массив;
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ВидИзменяемыхОбъектов);
		ОписаниеСтандартныхРеквизитов = ОбъектМетаданных.СтандартныеРеквизиты;// массив из ОписаниеСтандартногоРеквизита
		Для Каждого ОписаниеРеквизита Из ОписаниеСтандартныхРеквизитов Цикл
			НеРедактируемые.Добавить(ОписаниеРеквизита.Имя);
		КонецЦикла;
		
		ОписаниеРеквизитов = ОбъектМетаданных.Реквизиты;// массив из ОбъектМетаданныхРеквизит
		Для Каждого ОписаниеРеквизита Из ОписаниеРеквизитов Цикл
			НеРедактируемые.Добавить(ОписаниеРеквизита.Имя);
		КонецЦикла;
		
		Для Каждого ТабличнаяЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
			Если Редактируемые.Найти(ТабличнаяЧасть.Имя + ".*") <> Неопределено Тогда
				Прервать;
			КонецЕсли;
			ОписаниеРеквизитовТабличнойЧасти = ТабличнаяЧасть.Реквизиты;// массив из ОбъектМетаданныхРеквизит
			Для Каждого Реквизит Из ОписаниеРеквизитовТабличнойЧасти Цикл
				НеРедактируемые.Добавить(ТабличнаяЧасть.Имя + "." + Реквизит.Имя);
			КонецЦикла;
		КонецЦикла;
		
		Для Каждого ИмяРедактируемого Из Редактируемые Цикл
			Индекс = НеРедактируемые.Найти(ИмяРедактируемого);
			Если Индекс = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			НеРедактируемые.Удалить(Индекс);
		КонецЦикла;
		
		Для Каждого ИмяРеквизита Из НеРедактируемые Цикл
			ИменаРеквизитов.Вставить(ИмяРеквизита);
		КонецЦикла;
	КонецЦикла;
	
	Для Каждого Элемент Из ИменаРеквизитов Цикл
		ИмяРеквизита = Элемент.Ключ;
		Результат.Добавить(ИмяРеквизита);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Функция ФильтруемыеРеквизиты()

	Если Объект.ПоказыватьСлужебныеРеквизиты Тогда
		Возврат Новый Массив;
	КонецЕсли;
	
	ДоступностьОбъектов = ДоступностьОбъектов();
	
	Для Каждого ИмяТипа Из СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь) Цикл
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяТипа);
		ФильтруемыеРеквизиты = ФильтрРедактированияПоТипу(ОбъектМетаданных);
		
		ЗакрытыеФункциональнымиОпциями = Новый Соответствие;
		
		ОписаниеРеквизитов = ОбъектМетаданных.Реквизиты;// массив из ОбъектМетаданныхРеквизит
		Для Каждого Реквизит Из ОписаниеРеквизитов Цикл
			Если ДоступностьОбъектов[Реквизит] = Ложь Тогда
				ЗакрытыеФункциональнымиОпциями.Вставить(Реквизит.Имя, Истина);
			КонецЕсли;
		КонецЦикла;
		
		ОписаниеТабличныхЧастей = ОбъектМетаданных.ТабличныеЧасти;// массив из ОбъектМетаданныхТабличнаяЧасть
		Для Каждого ТабличнаяЧасть Из ОписаниеТабличныхЧастей Цикл
			Если ДоступностьОбъектов[ТабличнаяЧасть] = Ложь Тогда
				ЗакрытыеФункциональнымиОпциями.Вставить(ТабличнаяЧасть.Имя + ".*", Истина);
			Иначе
				Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
					Если ДоступностьОбъектов[Реквизит] = Ложь Тогда
						ЗакрытыеФункциональнымиОпциями.Вставить(ТабличнаяЧасть.Имя + "." + Реквизит.Имя, Истина);
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
		
		Для Каждого РеквизитЗакрытыйФункциональнымиОпциями Из ЗакрытыеФункциональнымиОпциями Цикл
			ФильтруемыеРеквизиты.Вставить(РеквизитЗакрытыйФункциональнымиОпциями.Ключ, Истина);
		КонецЦикла;
		
	КонецЦикла;
		
	Результат = Новый Массив;
	Для Каждого Реквизит Из ФильтруемыеРеквизиты Цикл
		Результат.Добавить(Реквизит.Ключ);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Процедура ЗаполнитьТабличныеЧастиОбъектов(ЗаблокированныеРеквизиты, НередактируемыеРеквизиты, ФильтруемыеРеквизиты, ДоступныеТабличныеЧасти)
	
	СписокВидовИзменяемыхОбъектов = СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь);
	ИмяОбъекта = СписокВидовИзменяемыхОбъектов[0];
	
	ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяОбъекта);
	
	// Создание реквизитов для табличных частей.
	НовыеРеквизитыФормы = Новый Массив;
	
	КолонкиТаблиц = ОписанияКолонокТаблицыРеквизитов();
	
	ТаблицыОбъекта = Новый Структура;
	ТабличныеЧастиОбъекта.Очистить();
	Для Каждого ОписаниеТабличнойЧасти Из ОбъектМетаданных.ТабличныеЧасти Цикл
		Если Не ДоступныеТабличныеЧасти.Свойство(ОписаниеТабличнойЧасти.Имя) Тогда
			Продолжить;
		КонецЕсли;
			
		Если Не ПравоДоступа("Редактирование", ОписаниеТабличнойЧасти) Тогда
			Продолжить;
		КонецЕсли;
		// фильтры табличных частей
		Если НередактируемыеРеквизиты.Найти(ОписаниеТабличнойЧасти.Имя + ".*") <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Если ФильтруемыеРеквизиты.Найти(ОписаниеТабличнойЧасти.Имя + ".*") <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ДоступныеДляИзмененияРеквизиты = ДоступныеДляИзмененияРеквизиты(ОписаниеТабличнойЧасти, НередактируемыеРеквизиты,
			ФильтруемыеРеквизиты, ДоступныеТабличныеЧасти[ОписаниеТабличнойЧасти.Имя]);
			
		Если ДоступныеДляИзмененияРеквизиты.Количество() = 0 Тогда
			Продолжить;
		КонецЕсли;
		
		ИмяРеквизита = "ТабличнаяЧасть" + ОписаниеТабличнойЧасти.Имя;
		ТаблицаЗначений = Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("ТаблицаЗначений"), , ОписаниеТабличнойЧасти.Представление());
		НовыеРеквизитыФормы.Добавить(ТаблицаЗначений);
		
		Для Каждого ОписаниеКолонки Из КолонкиТаблиц Цикл 
			РеквизитТаблицы = Новый РеквизитФормы(ОписаниеКолонки.Имя, ОписаниеКолонки.Тип, ТаблицаЗначений.Имя, ОписаниеКолонки.Представление);
			НовыеРеквизитыФормы.Добавить(РеквизитТаблицы);
		КонецЦикла;
		
		ТаблицыОбъекта.Вставить(ИмяРеквизита, ОписаниеТабличнойЧасти);
		ТабличныеЧастиОбъекта.Добавить(ИмяРеквизита, ОписаниеТабличнойЧасти.Представление());
	КонецЦикла;
	ИзменитьРеквизиты(НовыеРеквизитыФормы);
	
	Для Каждого ТаблицаОбъекта Из ТаблицыОбъекта Цикл
		ИмяРеквизита = ТаблицаОбъекта.Ключ;
		ИмяСтраницы = "Страница" + ИмяРеквизита;
		Страница = Элементы.Добавить(ИмяСтраницы, Тип("ГруппаФормы"), Элементы.СоставОбъекта);
		Страница.Вид = ВидГруппыФормы.Страница;
		ОписаниеТабличнойЧасти = ТаблицаОбъекта.Значение;
		Страница.Заголовок = ОписаниеТабличнойЧасти.Представление();
		
		// Создание элементов для табличных частей.
		ТаблицаФормы = Элементы.Добавить(ИмяРеквизита, Тип("ТаблицаФормы"), Страница);
		ТаблицаФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
		ТаблицаФормы.ПутьКДанным = ИмяРеквизита;
		ТаблицаФормы.ПоложениеКоманднойПанели = ПоложениеКоманднойПанелиЭлементаФормы.Нет;
		ТаблицаФормы.Заголовок = ОписаниеТабличнойЧасти.Представление();
		ТаблицаФормы.УстановитьДействие("ПередНачаломИзменения", "Подключаемый_ПередНачаломИзменения");
		ТаблицаФормы.ИзменятьПорядокСтрок = Ложь;
		ТаблицаФормы.ИзменятьСоставСтрок = Ложь;
		ТаблицаФормы.КартинкаСтрок = КартинкаВидыОпераций();
		ТаблицаФормы.ПутьКДаннымКартинкиСтроки = ИмяРеквизита + ".ВидОперации";
		ТаблицаФормы.Высота = 5;
		
		Для Каждого ОписаниеКолонки Из КолонкиТаблиц Цикл 
			Если ОписаниеКолонки.ВидПоля = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			ИмяРеквизита = ОписаниеКолонки.Имя;
			ИмяЭлемента = ТаблицаФормы.Имя + ИмяРеквизита;
			КолонкаТаблицы = Элементы.Добавить(ИмяЭлемента, Тип("ПолеФормы"), ТаблицаФормы);
			Если ОписаниеКолонки.Картинка <> Неопределено Тогда
				КолонкаТаблицы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
				КолонкаТаблицы.КартинкаШапки = ОписаниеКолонки.Картинка;
			КонецЕсли;
			КолонкаТаблицы.ПутьКДанным = ТаблицаОбъекта.Ключ + "." + ИмяРеквизита;
			КолонкаТаблицы.Вид = ОписаниеКолонки.ВидПоля;
			КолонкаТаблицы.РежимРедактирования = РежимРедактированияКолонки.ВходПриВводе;
			КолонкаТаблицы.ТолькоПросмотр = ОписаниеКолонки.ТолькоПросмотр;
			Если ОписаниеКолонки.Действия <> Неопределено Тогда
				Для Каждого Действие Из ОписаниеКолонки.Действия Цикл
					КолонкаТаблицы.УстановитьДействие(Действие.Ключ, Действие.Значение);
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
		
		ДоступныеДляИзмененияРеквизиты = ДоступныеДляИзмененияРеквизиты(ОписаниеТабличнойЧасти, НередактируемыеРеквизиты,
			ФильтруемыеРеквизиты, ДоступныеТабличныеЧасти[ОписаниеТабличнойЧасти.Имя]);	
			
		Для Каждого ОписаниеРеквизита Из ДоступныеДляИзмененияРеквизиты Цикл
			ДанныеФормыТаблица = ЭтотОбъект[ТаблицаОбъекта.Ключ];// см. ОписанияКолонокТаблицыРеквизитов
			Реквизит = ДанныеФормыТаблица.Добавить();
			Реквизит.Имя = ОписаниеРеквизита.Имя;
			Реквизит.Представление = ?(ПустаяСтрока(ОписаниеРеквизита.Представление()), ОписаниеРеквизита.Имя, ОписаниеРеквизита.Представление());
			Реквизит.ДопустимыеТипы = ОписаниеРеквизита.Тип;
			Реквизит.СвязиПараметровВыбора = СвязиПараметровВыбораСтрокой(ОписаниеРеквизита.СвязиПараметровВыбора);
			Реквизит.ПараметрыВыбора = ПараметрыВыбораСтрокой(ОписаниеРеквизита.ПараметрыВыбора);
			Реквизит.ВидОперации = 1;
			Реквизит.ПредставлениеСвязейПараметровВыбора = ПредставлениеСвязейПараметровВыбора(ОписаниеРеквизита.СвязиПараметровВыбора, ОбъектМетаданных);
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//   ОписаниеТабличнойЧасти - Структура:
//   * Реквизиты - Массив из ОбъектМетаданныхРеквизит
//   НередактируемыеРеквизиты - Массив из Строка
//   ФильтруемыеРеквизиты - Массив
//   ДоступныеРеквизиты - Массив
// Возвращаемое значение:
//   Массив из ОбъектМетаданныхРеквизит
//
&НаСервере
Функция ДоступныеДляИзмененияРеквизиты(ОписаниеТабличнойЧасти, НередактируемыеРеквизиты, ФильтруемыеРеквизиты, ДоступныеРеквизиты)
	
	Результат = Новый Массив;
	
	Для Каждого ОписаниеРеквизита Из ОписаниеТабличнойЧасти.Реквизиты Цикл
		Если ДоступныеРеквизиты.Найти(ОписаниеРеквизита.Имя) = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не ПравоДоступа("Редактирование", ОписаниеРеквизита) Тогда
			Продолжить;
		КонецЕсли;
		// Фильтры реквизитов табличных частей.
		Если НередактируемыеРеквизиты.Найти(ОписаниеТабличнойЧасти.Имя + "." + ОписаниеРеквизита.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Если ФильтруемыеРеквизиты.Найти(ОписаниеТабличнойЧасти.Имя + "." + ОписаниеРеквизита.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Результат.Добавить(ОписаниеРеквизита);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции


// Возвращаемое значение:
//   ТаблицаЗначений:
//   * Имя - Строка
//   * Тип - Строка
//   * Представление - Строка 
//   * ВидПоля - Строка
//   * Действия - Структура:
//   ** ПриИзменении - Булево
//   ** Подключаемый_ПриИзмененииФлажка - Булево
//   * ТолькоПросмотр - Булево
//   * Картинка - Картинка
//
&НаСервере
Функция ОписанияКолонокТаблицыРеквизитов()
	
	КолонкиТаблиц = Новый ТаблицаЗначений;
	КолонкиТаблиц.Колонки.Добавить("Имя");
	КолонкиТаблиц.Колонки.Добавить("Тип");
	КолонкиТаблиц.Колонки.Добавить("Представление");
	КолонкиТаблиц.Колонки.Добавить("ВидПоля");
	КолонкиТаблиц.Колонки.Добавить("Действия");
	КолонкиТаблиц.Колонки.Добавить("ТолькоПросмотр", Новый ОписаниеТипов("Булево"));
	КолонкиТаблиц.Колонки.Добавить("Картинка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "Имя";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "Представление";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	ОписаниеКолонки.Представление = НСтр("ru = 'Реквизит'");
	ОписаниеКолонки.ВидПоля = ВидПоляФормы.ПолеВвода;
	ОписаниеКолонки.ТолькоПросмотр = Истина;
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "Изменять";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Булево");
	ОписаниеКолонки.ВидПоля = ВидПоляФормы.ПолеФлажка;
	ОписаниеКолонки.Картинка = БиблиотекаКартинок.Изменить;
	ОписаниеКолонки.Действия = Новый Структура("ПриИзменении", "Подключаемый_ПриИзмененииФлажка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "Значение";
	ОписаниеКолонки.Тип = ВсеТипы();
	ОписаниеКолонки.Представление = НСтр("ru = 'Новое значение'");
	ОписаниеКолонки.ВидПоля = ВидПоляФормы.ПолеВвода;
	ОписаниеКолонки.Действия = Новый Структура("ПриИзменении", "Подключаемый_ЗначениеПриИзменении");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "ДопустимыеТипы";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("ОписаниеТипов");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "СвязиПараметровВыбора";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "ПараметрыВыбора";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "ВидОперации";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Число");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "Свойство";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "ВыборГруппИЭлементов";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	ОписаниеКолонки = КолонкиТаблиц.Добавить();
	ОписаниеКолонки.Имя = "ПредставлениеСвязейПараметровВыбора";
	ОписаниеКолонки.Тип = Новый ОписаниеТипов("Строка");
	
	Возврат КолонкиТаблиц;
	
КонецФункции

&НаСервере
Функция ВсеТипы()
	Результат = Неопределено;
	Реквизиты = ПолучитьРеквизиты("РеквизитыОбъекта");
	Для Каждого Реквизит Из Реквизиты Цикл
		Если Реквизит.Имя = "Значение" Тогда
			Результат = Реквизит.ТипЗначения;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

&НаКлиенте
Процедура УстановитьОграниченияВыбираемыхТиповИПараметрыВыбораЗначения(ТабличноеПоле)
	Если ТабличноеПоле.ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПолеВвода = ТабличноеПоле.ПодчиненныеЭлементы[ТабличноеПоле.Имя + "Значение"];
	ПолеВвода.ОграничениеТипа = ТабличноеПоле.ТекущиеДанные.ДопустимыеТипы;
	
	Если ПолеВвода.ОграничениеТипа.Типы().Количество() = 1 И ПолеВвода.ОграничениеТипа.СодержитТип(Тип("Строка")) Тогда
		ПолеВвода.КнопкаВыбора = Истина;
	КонецЕсли;
	
	ПараметрыВыбораМассив = Новый Массив;
	
	Если НЕ ПустаяСтрока(ТабличноеПоле.ТекущиеДанные.ПараметрыВыбора) Тогда
		УстановитьПараметрыВыбораСервер(ТабличноеПоле.ТекущиеДанные.ПараметрыВыбора, ПараметрыВыбораМассив)
	КонецЕсли;
	
	Если Не ПустаяСтрока(ТабличноеПоле.ТекущиеДанные.СвязиПараметровВыбора) Тогда
		Для Индекс = 1 По СтрЧислоСтрок(ТабличноеПоле.ТекущиеДанные.СвязиПараметровВыбора) Цикл
			СвязьПараметровВыбораСтрока = СтрПолучитьСтроку(ТабличноеПоле.ТекущиеДанные.СвязиПараметровВыбора, Индекс);
			РазложенныеСтроки = СтрРазделить(СвязьПараметровВыбораСтрока, ";");
			ИмяПараметра = СокрЛП(РазложенныеСтроки[0]);
			
			ИмяРеквизита = СокрЛП(РазложенныеСтроки[1]);
			ЧастиИмениРеквизита = СтрРазделить(ИмяРеквизита, ".", Ложь);
			ИмяТабличнойЧасти = "";
			Если ЧастиИмениРеквизита.Количество() > 1 Тогда
				ИмяТабличнойЧасти = ЧастиИмениРеквизита[0];
			КонецЕсли;
			ИмяРеквизита = ЧастиИмениРеквизита[ЧастиИмениРеквизита.Количество() - 1];
			
			ТаблицаРеквизитов = РеквизитыОбъекта;
			Если Не ПустаяСтрока(ИмяТабличнойЧасти) Тогда
				ТаблицаРеквизитов = ЭтотОбъект["ТабличнаяЧасть" + ИмяТабличнойЧасти];
			КонецЕсли;
			
			НайденныеСтроки = ТаблицаРеквизитов.НайтиСтроки(Новый Структура("ВидОперации,Имя", 1, ИмяРеквизита));
			Если НайденныеСтроки.Количество() = 1 Тогда
				Значение = НайденныеСтроки[0].Значение;
				Если ЗначениеЗаполнено(Значение) Тогда
					ПараметрыВыбораМассив.Добавить(Новый ПараметрВыбора(ИмяПараметра, Значение));
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ТабличноеПоле.ТекущиеДанные.Свойство) Тогда
		ПараметрыВыбораМассив.Добавить(Новый ПараметрВыбора("Отбор.Владелец", ТабличноеПоле.ТекущиеДанные.Свойство));
	КонецЕсли;
	
	Если ОтключитьСвязиПараметровВыбора Тогда
		ПолеВвода.ПараметрыВыбора = Новый ФиксированныйМассив(Новый Массив);
	Иначе
		ПолеВвода.ПараметрыВыбора = Новый ФиксированныйМассив(ПараметрыВыбораМассив);
	КонецЕсли;
	
	ВыборГруппИЭлементов = ТабличноеПоле.ТекущиеДанные.ВыборГруппИЭлементов;
	
	Если ВыборГруппИЭлементов <> "" Тогда
		Если ВыборГруппИЭлементов = "Группы" Тогда
			ПолеВвода.ВыборГруппИЭлементов = ГруппыИЭлементы.Группы;
		ИначеЕсли ВыборГруппИЭлементов = "ГруппыИЭлементы" Тогда
			ПолеВвода.ВыборГруппИЭлементов = ГруппыИЭлементы.ГруппыИЭлементы;
		ИначеЕсли ВыборГруппИЭлементов = "Элементы" Тогда
			ПолеВвода.ВыборГруппИЭлементов = ГруппыИЭлементы.Элементы;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьСчетчикиИзменяемыхРеквизитов(Знач ТаблицаФормы = Неопределено)
	
	СписокТаблиц = Новый Массив;
	Если ТаблицаФормы <> Неопределено Тогда
		СписокТаблиц.Добавить(ТаблицаФормы);
	Иначе
		СписокТаблиц.Добавить(Элементы.РеквизитыОбъекта);
		Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
			СписокТаблиц.Добавить(Элементы[ТабличнаяЧасть.Значение]);
		КонецЦикла;
	КонецЕсли;
	
	Для Каждого ТаблицаФормы Из СписокТаблиц Цикл
		ТабличнаяЧасть = ЭтотОбъект[ТаблицаФормы.Имя];
		КоличествоИзменяемых = 0;
		Для Каждого Реквизит Из ТабличнаяЧасть Цикл
			Если Реквизит.Изменять Тогда
				КоличествоИзменяемых = КоличествоИзменяемых + 1;
			КонецЕсли;
		КонецЦикла;
	
		Страница = ТаблицаФормы.Родитель;// ГруппаФормы
		Страница.Заголовок = ТаблицаФормы.Заголовок + ?(КоличествоИзменяемых = 0, "", " (" + КоличествоИзменяемых+ ")");
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Процедура ОбновитьВидимостьЭлементов()
	Если ТабличныеЧастиОбъекта.Количество() = 0 Тогда
		Элементы.СоставОбъекта.ОтображениеСтраниц = ОтображениеСтраницФормы.Нет;
	Иначе
		Элементы.СоставОбъекта.ОтображениеСтраниц = ОтображениеСтраницФормы.ЗакладкиСверху;
	КонецЕсли;
	
	Если Не ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
		ЕстьОбщиеРеквизиты = РеквизитыОбъекта.Количество() > 0;
		Элементы.ГруппаНетРеквизитов.Видимость = Не ЕстьОбщиеРеквизиты;
		Если Объект.ТипОперации = "ВыполнитьАлгоритм" Тогда
			Элементы.Алгоритмы.Видимость = Истина;
		Иначе
			Элементы.РанееИзмененныеРеквизиты.Видимость = ЕстьОбщиеРеквизиты Или ТабличныеЧастиОбъекта.Количество() > 0;
		КонецЕсли;
		Элементы.РеквизитыОбъекта.Видимость = ЕстьОбщиеРеквизиты;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьРеквизитыОбъекта(БлокируемыеРеквизиты, НеРедактируемые, ФильтруемыеРеквизиты, ДоступныеРеквизиты)
	
	РеквизитыОбъекта.Очистить();
	
	СписокВидовИзменяемыхОбъектов = СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь);
	Если СписокВидовИзменяемыхОбъектов.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	НаборыРеквизитов = Новый Структура;
	НаборыРеквизитов.Вставить("НеРедактируемые", НеРедактируемые);
	НаборыРеквизитов.Вставить("Фильтруемые", ФильтруемыеРеквизиты);
	НаборыРеквизитов.Вставить("Блокируемые", БлокируемыеРеквизиты);
	НаборыРеквизитов.Вставить("Доступные", ДоступныеРеквизиты);
	
	ИмяОбъекта = СписокВидовИзменяемыхОбъектов[0];
	ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ИмяОбъекта);
	НаборыРеквизитов.Вставить("ОписанияРеквизитов", ОбъектМетаданных.СтандартныеРеквизиты);
	ДобавитьРеквизитыВНабор(НаборыРеквизитов, ОбъектМетаданных);
	
	НаборыРеквизитов.Вставить("ОписанияРеквизитов", ОбъектМетаданных.Реквизиты);
	ДобавитьРеквизитыВНабор(НаборыРеквизитов, ОбъектМетаданных);
	
	РеквизитыОбъекта.Сортировать("Представление Возр");
	
	Если ПодсистемаСуществует("СтандартныеПодсистемы.Свойства") Тогда
		МодульУправлениеСвойствами = ОбщийМодуль("УправлениеСвойствами");
		Если МодульУправлениеСвойствами <> Неопределено Тогда
			ИспользуютсяДопРеквизиты = Истина;
			ИспользуютсяДопСведения = Истина;
			Для Каждого ВидОбъекта Из СписокВидовИзменяемыхОбъектов Цикл
				МенеджерОбъекта = МенеджерОбъектаПоПолномуИмени(ВидОбъекта);
				ИспользуютсяДопРеквизиты = ИспользуютсяДопРеквизиты И МодульУправлениеСвойствами.ИспользоватьДопРеквизиты(МенеджерОбъекта.ПустаяСсылка());
				ИспользуютсяДопСведения  = ИспользуютсяДопСведения И МодульУправлениеСвойствами.ИспользоватьДопСведения (МенеджерОбъекта.ПустаяСсылка());
			КонецЦикла;
			Если ИспользуютсяДопРеквизиты Или ИспользуютсяДопСведения Тогда
				ДобавитьДополнительныеРеквизитыИСведенияВНабор();
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ДобавитьДополнительныеРеквизитыИСведенияВНабор()
	
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	
	СписокВидовИзменяемыхОбъектов = СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь);
	ОбщийСписокРеквизитов = СписокСвойствДляВидаОбъектов(СписокВидовИзменяемыхОбъектов[0]);
	Для Индекс = 1 По СписокВидовИзменяемыхОбъектов.Количество() - 1 Цикл
		ОбщийСписокРеквизитов = ОбработкаОбъект.ПересечениеМножеств(ОбщийСписокРеквизитов, СписокСвойствДляВидаОбъектов(СписокВидовИзменяемыхОбъектов[Индекс]));
	КонецЦикла;
	
	ДобавляемыеСвойства = Новый Массив;
	
	Если КонтекстныйВызов Тогда
		НастройкиОтбора = НастройкиОтбора();
		НастройкиОтбора.ОбновитьСписок = Истина;
		ВыбранныеОбъекты = ВыбранныеОбъекты(НастройкиОтбора).Строки;
		Для Каждого ДанныеОбъекта Из ВыбранныеОбъекты Цикл
			ОбъектДляИзменения = ДанныеОбъекта.Ссылка;
			
			ВидОбъектаПоСсылке = ВидОбъектаПоСсылке(ОбъектДляИзменения);
			Если (ВидОбъектаПоСсылке = "Справочник" ИЛИ ВидОбъектаПоСсылке = "ПланВидовХарактеристик") И ОбъектЯвляетсяГруппой(ОбъектДляИзменения) Тогда
				Продолжить;
			КонецЕсли;
			
			МодульУправлениеСвойствами = ОбщийМодуль("УправлениеСвойствами");
			СписокСвойств = МодульУправлениеСвойствами.СвойстваОбъекта(ОбъектДляИзменения);
			Для Каждого Свойство Из СписокСвойств Цикл
				Если ОбщийСписокРеквизитов.Найти(Свойство) = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если ДобавляемыеСвойства.Найти(Свойство) <> Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				ДобавляемыеСвойства.Добавить(Свойство);
			КонецЦикла;
		КонецЦикла;
	Иначе
		ДобавляемыеСвойства = ОбщийСписокРеквизитов;
	КонецЕсли;
	
	ДобавитьСвойстваВСписокРеквизитов(ДобавляемыеСвойства);
	РеквизитыОбъекта.Сортировать("Представление");
	
КонецПроцедуры

&НаСервере
Процедура ДобавитьСвойстваВСписокРеквизитов(Свойства)
	
	МодульОбщегоНазначения = ОбщийМодуль("ОбщегоНазначения");
	ОписанияСвойств = МодульОбщегоНазначения.ЗначенияРеквизитовОбъектов(Свойства, "Ссылка,Наименование,ТипЗначения,ЭтоДополнительноеСведение");
	Для Каждого Свойство Из Свойства Цикл
		ОписаниеСвойства = ОписанияСвойств[Свойство];
		ОписаниеРеквизита = РеквизитыОбъекта.Добавить();
		ОписаниеРеквизита.ВидОперации = ?(ОписаниеСвойства.ЭтоДополнительноеСведение, 3, 2);
		ОписаниеРеквизита.Свойство = ОписаниеСвойства.Ссылка;
		ОписаниеРеквизита.Представление = ОписаниеСвойства.Наименование;
		ОписаниеРеквизита.ДопустимыеТипы = ОписаниеСвойства.ТипЗначения;
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Функция СписокСвойствДляВидаОбъектов(ВидОбъектов)
	Результат = Новый Массив;
	
	ВидыСвойств = Новый Массив;
	ВидыСвойств.Добавить("ДополнительныеРеквизиты");
	ВидыСвойств.Добавить("ДополнительныеСведения");
	
	МодульУправлениеСвойствамиСлужебный = ОбщийМодуль("УправлениеСвойствамиСлужебный");
	Если МодульУправлениеСвойствамиСлужебный <> Неопределено Тогда
		Для Каждого ВидСвойства Из ВидыСвойств Цикл
			СписокСвойств = МодульУправлениеСвойствамиСлужебный.СписокСвойствДляВидаОбъектов(ВидОбъектов, ВидСвойства);
			Если СписокСвойств <> Неопределено Тогда
				Для Каждого Элемент Из СписокСвойств Цикл
					Результат.Добавить(Элемент.Свойство);
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

&НаСервере
Процедура ДобавитьРеквизитыВНабор(НаборыРеквизитов, ОбъектМетаданных)
	
	Реквизиты = НаборыРеквизитов.ОписанияРеквизитов;
	НеРедактируемые = НаборыРеквизитов.НеРедактируемые;
	ФильтруемыеРеквизиты = НаборыРеквизитов.Фильтруемые;
	БлокируемыеРеквизиты = НаборыРеквизитов.Блокируемые;
	СписокДоступныхРеквизитов = НаборыРеквизитов.Доступные;
	
	Для Каждого ОписаниеРеквизита Из Реквизиты Цикл
		Если СписокДоступныхРеквизитов.Найти(ОписаниеРеквизита.Имя) = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если ТипЗнч(ОписаниеРеквизита) = Тип("ОписаниеСтандартногоРеквизита") Тогда
			Если НЕ ПравоДоступа("Редактирование", ОбъектМетаданных, , ОписаниеРеквизита.Имя) Тогда
				Продолжить;
			КонецЕсли;
		Иначе
			Если НЕ ПравоДоступа("Редактирование", ОписаниеРеквизита) Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		
		Если НеРедактируемые.Найти(ОписаниеРеквизита.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если ФильтруемыеРеквизиты.Найти(ОписаниеРеквизита.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ВыборГруппИЭлементов = "";
		Если ТипЗнч(ОписаниеРеквизита) = Тип("ОписаниеСтандартногоРеквизита") Тогда
			Если ОписаниеРеквизита.Имя = "Родитель" Или ОписаниеРеквизита.Имя = "Parent" Тогда
				ВыборГруппИЭлементов = "Группы";
			ИначеЕсли ОписаниеРеквизита.Имя = "Владелец" Или ОписаниеРеквизита.Имя = "Owner" Тогда
				Если ОбъектМетаданных.ИспользованиеПодчинения = Метаданные.СвойстваОбъектов.ИспользованиеПодчинения.Элементам Тогда
					ВыборГруппИЭлементов = "Элементы";
				ИначеЕсли ОбъектМетаданных.ИспользованиеПодчинения = Метаданные.СвойстваОбъектов.ИспользованиеПодчинения.ГруппамИЭлементам Тогда
					ВыборГруппИЭлементов = "ГруппыИЭлементы";
				ИначеЕсли ОбъектМетаданных.ИспользованиеПодчинения = Метаданные.СвойстваОбъектов.ИспользованиеПодчинения.Группам Тогда
					ВыборГруппИЭлементов = "Группы";
				КонецЕсли;
			КонецЕсли;
		Иначе
			ЭтоСсылка = Ложь;
			
			Для Каждого Тип Из ОписаниеРеквизита.Тип.Типы() Цикл
				Если ЭтоСсылка(Тип) Тогда
					ЭтоСсылка = Истина;
					Прервать;
				КонецЕсли;
			КонецЦикла;
			
			Если ЭтоСсылка Тогда
				Если ОписаниеРеквизита.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.Группы Тогда
					ВыборГруппИЭлементов = "Группы";
				ИначеЕсли ОписаниеРеквизита.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.ГруппыИЭлементы Тогда
					ВыборГруппИЭлементов = "ГруппыИЭлементы";
				ИначеЕсли ОписаниеРеквизита.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.Элементы Тогда
					ВыборГруппИЭлементов = "Элементы";
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		
		СписокВидовИзменяемыхОбъектов = СтрРазделить(ВидыИзменяемыхОбъектов, ",", Ложь);
		ПредставлениеСвязейПараметровВыбора = "";
		Если СписокВидовИзменяемыхОбъектов.Количество() = 1 Тогда
			ПараметрыВыбораСтрока = ПараметрыВыбораСтрокой(ОписаниеРеквизита.ПараметрыВыбора);
			СвязиПараметровВыбораСтрока = СвязиПараметровВыбораСтрокой(ОписаниеРеквизита.СвязиПараметровВыбора);
			ПредставлениеСвязейПараметровВыбора = ПредставлениеСвязейПараметровВыбора(ОписаниеРеквизита.СвязиПараметровВыбора, ОбъектМетаданных);
		Иначе
			ПараметрыВыбораСтрока = ПараметрыВыбораСтрокой(Новый Массив);
			СвязиПараметровВыбораСтрока = СвязиПараметровВыбораСтрокой(Новый Массив);
		КонецЕсли;
		
		РеквизитОбъекта = РеквизитыОбъекта.Добавить();
		РеквизитОбъекта.Имя = ОписаниеРеквизита.Имя;
		РеквизитОбъекта.Представление = ОписаниеРеквизита.Представление();
		
		РеквизитОбъекта.ДопустимыеТипы = ОписаниеРеквизита.Тип;
		РеквизитОбъекта.ПараметрыВыбора = ПараметрыВыбораСтрока;
		РеквизитОбъекта.СвязиПараметровВыбора = СвязиПараметровВыбораСтрока;
		РеквизитОбъекта.ПредставлениеСвязейПараметровВыбора = ПредставлениеСвязейПараметровВыбора;
		РеквизитОбъекта.ВыборГруппИЭлементов = ВыборГруппИЭлементов;
		РеквизитОбъекта.ВидОперации = 1;
		
		Если БлокируемыеРеквизиты.Найти(ОписаниеРеквизита.Имя) <> Неопределено Тогда
			РеквизитОбъекта.ЗаблокированныйРеквизит = Истина;
		КонецЕсли;
		
		РеквизитОбъекта.ЭтоСтандартныйРеквизит = ТипЗнч(ОписаниеРеквизита) = Тип("ОписаниеСтандартногоРеквизита");
		
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Функция ФильтрРеквизитов()

	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("ТипОбъекта", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(80)));
	Результат.Колонки.Добавить("Реквизит", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(80)));
	
	// Все объекты.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "*";
	Фильтр.Реквизит = "Наименование";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "*";
	Фильтр.Реквизит = "ПометкаУдаления";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "*";
	Фильтр.Реквизит = "Ссылка";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "*";
	Фильтр.Реквизит = "ДополнительныеРеквизиты.*";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "*";
	Фильтр.Реквизит = "КонтактнаяИнформация.*";

	// Справочники.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Справочники";
	Фильтр.Реквизит = "ИмяПредопределенныхДанных";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Справочники";
	Фильтр.Реквизит = "Код";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Справочники";
	Фильтр.Реквизит = "Предопределенный";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Справочники";
	Фильтр.Реквизит = "ЭтоГруппа";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Справочники";
	Фильтр.Реквизит = "РеквизитДопУпорядочивания";
	
	// Документы.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Документы";
	Фильтр.Реквизит = "Номер";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Документы";
	Фильтр.Реквизит = "Проведен";
	
	// Планы видов характеристик.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовХарактеристик";
	Фильтр.Реквизит = "ИмяПредопределенныхДанных";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовХарактеристик";
	Фильтр.Реквизит = "Код";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовХарактеристик";
	Фильтр.Реквизит = "Предопределенный";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовХарактеристик";
	Фильтр.Реквизит = "ЭтоГруппа";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовХарактеристик";
	Фильтр.Реквизит = "ТипЗначения";
	
	// Планы счетов.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыСчетов";
	Фильтр.Реквизит = "ИмяПредопределенныхДанных";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыСчетов";
	Фильтр.Реквизит = "Код";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыСчетов";
	Фильтр.Реквизит = "Предопределенный";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыСчетов";
	Фильтр.Реквизит = "Порядок";

	// Планы видов расчета.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовРасчета";
	Фильтр.Реквизит = "ИмяПредопределенныхДанных";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовРасчета";
	Фильтр.Реквизит = "Код";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовРасчета";
	Фильтр.Реквизит = "Предопределенный";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыВидовРасчета";
	Фильтр.Реквизит = "ПериодДействияБазовый";
	
	// Задачи.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "Задачи";
	Фильтр.Реквизит = "Номер";
	
	// Бизнес-процессы.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "БизнесПроцессы";
	Фильтр.Реквизит = "Номер";

	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "БизнесПроцессы";
	Фильтр.Реквизит = "Дата";
	
	// Планы обмена.
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыОбмена";
	Фильтр.Реквизит = "Код";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыОбмена";
	Фильтр.Реквизит = "НомерОтправленного";
	
	Фильтр = Результат.Добавить();
	Фильтр.ТипОбъекта = "ПланыОбмена";
	Фильтр.Реквизит = "НомерПринятого";
	
	Результат.Индексы.Добавить("ТипОбъекта");
	
	Возврат Результат;
КонецФункции
	
// Получает массив реквизитов, редактирование которых не предусмотрено на уровне конфигурации.
//
// Параметры:
//   ОбъектМетаданных - ОбъектМетаданных
// 
// Возвращаемое значение:
//   Соответствие
//
&НаСервере
Функция ФильтрРедактированияПоТипу(ОбъектМетаданных)
	
	ФильтрТаблица = ФильтрРеквизитов();
	
	// Реквизиты, блокируемые для любого типа объектов метаданных.
	ОбщийФильтр = ФильтрТаблица.НайтиСтроки(Новый Структура("ТипОбъекта", "*"));
	
	// Реквизиты, блокируемые для указанного типа объектов метаданных.
	ФильтрПоТипуОбъекта = ФильтрТаблица.НайтиСтроки(Новый Структура("ТипОбъекта", 
		ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных)));
	
	ФильтруемыеРеквизиты = Новый Соответствие;
	
	Для Каждого СтрокаОписание Из ОбщийФильтр Цикл
		ФильтруемыеРеквизиты[СтрокаОписание.Реквизит] = Истина;
	КонецЦикла;
	
	Для Каждого СтрокаОписание Из ФильтрПоТипуОбъекта Цикл
		ФильтруемыеРеквизиты[СтрокаОписание.Реквизит] = Истина;
	КонецЦикла;
	
	ПрефиксУдаляемыхРеквизитов = "Удалить";
	ОписаниеРеквизитов = ОбъектМетаданных.Реквизиты; // Массив из ОбъектМетаданныхРеквизит
	Для Каждого Реквизит Из ОписаниеРеквизитов Цикл
		Если НРег(Лев(Реквизит.Имя, СтрДлина(ПрефиксУдаляемыхРеквизитов))) = НРег(ПрефиксУдаляемыхРеквизитов) Тогда
			ФильтруемыеРеквизиты[Реквизит.Имя] = Истина;
		КонецЕсли;
	КонецЦикла;
	Для Каждого ТабличнаяЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
		Если НРег(Лев(ТабличнаяЧасть.Имя, СтрДлина(ПрефиксУдаляемыхРеквизитов))) = НРег(ПрефиксУдаляемыхРеквизитов) Тогда
			ФильтруемыеРеквизиты[ТабличнаяЧасть.Имя + ".*"] = Истина;
		Иначе
			ОписаниеРеквизитовТабличнойЧасти = ТабличнаяЧасть.Реквизиты; // Массив из ОбъектМетаданныхРеквизит
			Для Каждого Реквизит Из ОписаниеРеквизитовТабличнойЧасти Цикл
				Если НРег(Лев(Реквизит.Имя, СтрДлина(ПрефиксУдаляемыхРеквизитов))) = НРег(ПрефиксУдаляемыхРеквизитов) Тогда
					ФильтруемыеРеквизиты[ТабличнаяЧасть.Имя + "." + Реквизит.Имя] = Истина;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ФильтруемыеРеквизиты;
	
КонецФункции

&НаСервере
Функция ЭлементыОтбораБезИерархии(Знач ЭлементыОтбора)
	Результат = Новый Массив;
	Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл
		Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
			ПодчиненныеОтборы = ЭлементыОтбораБезИерархии(ЭлементОтбора.Элементы);
			Для Каждого ПодчиненныйОтбор Из ПодчиненныеОтборы Цикл
				Результат.Добавить(ПодчиненныйОтбор);
			КонецЦикла;
		Иначе
			Результат.Добавить(ЭлементОтбора);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

&НаСервере
Процедура СформироватьПояснениеОНастроенныхИзменениях()
	
	ЕстьОтборПоСтрокам = Ложь;
	Для Каждого ЭлементОтбора Из ЭлементыОтбораБезИерархии(КомпоновщикНастроек.Настройки.Отбор.Элементы) Цикл
		Если Не ЭлементОтбора.Использование Тогда
			Продолжить;
		КонецЕсли;
		Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
			ИмяТабличнойЧасти = Сред(ТабличнаяЧасть.Значение, СтрДлина("ТабличнаяЧасть") + 1);
			Если СтрНачинаетсяС(ЭлементОтбора.ЛевоеЗначение, ИмяТабличнойЧасти) Тогда
				ЕстьОтборПоСтрокам = Истина;
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	ИзменяемыеТабличныеЧасти = Новый Соответствие;
	Для Каждого ТабличнаяЧасть Из ТабличныеЧастиОбъекта Цикл
		ИзменяемыеРеквизиты = Новый Массив;
		Для Каждого Реквизит Из ЭтотОбъект[ТабличнаяЧасть.Значение] Цикл
			Если Реквизит.Изменять Тогда
				ИзменяемыеРеквизиты.Добавить(Реквизит.Представление);
			КонецЕсли;
		КонецЦикла;
		Если ИзменяемыеРеквизиты.Количество() > 0 Тогда 
			ИзменяемыеТабличныеЧасти.Вставить(ТабличнаяЧасть.Представление, ИзменяемыеРеквизиты);
		КонецЕсли;
	КонецЦикла;
	
	ИзменяемыеРеквизиты = Новый Массив;
	Для Каждого Реквизит Из РеквизитыОбъекта Цикл
		Если Реквизит.Изменять Тогда
			ИзменяемыеРеквизиты.Добавить(Реквизит.Представление);
		КонецЕсли;
	КонецЦикла;
	
	Если Не ЕстьВыбранныеОбъекты() Тогда
		Пояснение = НСтр("ru = 'Не выбраны элементы, реквизиты которых необходимо изменить.'");
	Иначе
		Если ИзменяемыеРеквизиты.Количество() = 1 Тогда
			ШаблонПояснения = НСтр("ru = 'Изменить реквизит %1 в выбранных элементах'") // например, "Изменить реквизит ""Склад""..."
		ИначеЕсли ИзменяемыеРеквизиты.Количество() > 3 Тогда
			ШаблонПояснения = НСтр("ru = 'Изменить реквизиты (%1) в выбранных элементах'"); // например, "Изменить реквизиты (5)..."
		ИначеЕсли ИзменяемыеРеквизиты.Количество() > 1 Тогда
			ШаблонПояснения = НСтр("ru = 'Изменить реквизиты %1 в выбранных элементах'"); // например, "Изменить реквизиты ""Склад"", ""Офис""..."
		Иначе	
			ШаблонПояснения = "";
		КонецЕсли;
		
		Если ИзменяемыеРеквизиты.Количество() > 3 Тогда
			Пояснение = ПодставитьПараметрыВСтроку(ШаблонПояснения, ИзменяемыеРеквизиты.Количество());
		ИначеЕсли ИзменяемыеРеквизиты.Количество() > 0 Тогда
			Пояснение = ПодставитьПараметрыВСтроку(ШаблонПояснения, ИменаРеквизитов(ИзменяемыеРеквизиты));
		Иначе
			Пояснение = "";
		КонецЕсли;
		
		Для Каждого ТабличнаяЧасть Из ИзменяемыеТабличныеЧасти Цикл
			
			ИзменяемыеРеквизиты = ТабличнаяЧасть.Значение;
			Если ИзменяемыеРеквизиты.Количество() = 0 Тогда
				Продолжить;
			КонецЕсли;
			
			Если ИзменяемыеРеквизиты.Количество() = 1 Тогда
				ШаблонПояснения = ?(ПустаяСтрока(Пояснение),
					НСтр("ru = 'Изменить реквизит %1 в табличной части ""%2""'"),
					НСтр("ru = 'реквизит %1 в табличной части ""%2""'")); 
			ИначеЕсли ИзменяемыеРеквизиты.Количество() > 3 Тогда
				ШаблонПояснения = ?(ПустаяСтрока(Пояснение),
					НСтр("ru = 'Изменить реквизиты (%1) в табличной части ""%2""'"),
					НСтр("ru = 'реквизиты (%1) в табличной части ""%2""'")); 
			Иначе 
				ШаблонПояснения = ?(ПустаяСтрока(Пояснение),
					НСтр("ru = 'Изменить реквизиты %1 в табличной части ""%2""'"),
					НСтр("ru = 'реквизиты %1 в табличной части ""%2""'")); 
			КонецЕсли;
			
			Если Не ПустаяСтрока(Пояснение) Тогда
				Пояснение = Пояснение + ", ";
			КонецЕсли;
			Если ИзменяемыеРеквизиты.Количество() > 3 Тогда
				Пояснение = Пояснение + ПодставитьПараметрыВСтроку(ШаблонПояснения, 
					ИзменяемыеРеквизиты.Количество(), ТабличнаяЧасть.Ключ);
			Иначе
				Пояснение = Пояснение + ПодставитьПараметрыВСтроку(ШаблонПояснения, 
					ИменаРеквизитов(ИзменяемыеРеквизиты), ТабличнаяЧасть.Ключ);
			КонецЕсли;
		КонецЦикла;
		
		Если Не ПустаяСтрока(Пояснение) Тогда
			Пояснение = Пояснение + ".";
			Если ИзменяемыеТабличныеЧасти.Количество() > 0 Тогда
				Если ЕстьОтборПоСтрокам Тогда 
					Пояснение = Пояснение + " " + ПодставитьПараметрыВСтроку(НСтр(
						"ru = 'Изменения будут выполнены в тех строках выбранных элементов, которые удовлетворяют <a href = ""%1"">условиям отбора</a>.'"),
						"ПерейтиКНастройкеОтбора");
				Иначе
					Пояснение = Пояснение + " " + ПодставитьПараметрыВСтроку(НСтр(
						"ru = 'Изменения будут выполнены <a href = ""%1"">во всех строках</a> выбранных элементов.'"),
						"ПерейтиКНастройкеОтбора");
				КонецЕсли;
			КонецЕсли;
		Иначе
			Пояснение = НСтр("ru = 'Выполнить <b>перезапись</b> выбранных элементов.'");
		КонецЕсли;
	КонецЕсли;
	
	Элементы.ПояснениеОНастроенныхИзменениях.Заголовок = ФорматированнаяСтрока(Пояснение);
	Если ПустаяСтрока(КодАлгоритма) Тогда
		КодАлгоритма = ПодставитьПараметрыВСтроку(НСтр("ru='// Доступные переменные:
		|// %1 - обрабатываемый объект'"), "Объект") + Символы.ПС;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция ИменаРеквизитов(Знач ИзменяемыеРеквизиты)
	
	ИменаРеквизитов = "";
	Для Каждого Реквизит Из ИзменяемыеРеквизиты Цикл
		Если Не ПустаяСтрока(ИменаРеквизитов) Тогда
			ИменаРеквизитов = ИменаРеквизитов + ", ";
		КонецЕсли;
		ИменаРеквизитов = ИменаРеквизитов + """" + Реквизит + """";
	КонецЦикла;
	Возврат ИменаРеквизитов;

КонецФункции

&НаСервере
Функция ЕстьВыбранныеОбъекты()
	НастройкиОтбора = НастройкиОтбора();
	НастройкиОтбора.ОграничитьВыборку = Истина;
	Возврат ВыбранныеОбъекты(НастройкиОтбора).Строки.Количество() > 0;
КонецФункции

&НаСервере
Процедура ОбновитьНадписьКоличествоВыбранных()
	
	Если ЕстьНастроенныеОтборы() Тогда
		ТекстСообщенияОбОшибке = "";
		КоличествоВыбранныхОбъектов = КоличествоВыбранныхОбъектов(Истина, , ТекстСообщенияОбОшибке);
		ТекстНадписи = СтрокаСЧисломДляЛюбогоЯзыка(НСтр("ru = ';%1 элемент;;%1 элемента;%1 элементов;%1 элемента'"),
			КоличествоВыбранныхОбъектов);
	Иначе
		ТекстНадписи = НСтр("ru = 'Все элементы'");
	КонецЕсли;
	
	Элементы.НастройкаОтбора.Заголовок = ТекстНадписи;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПодменюРанееИзмененныеРеквизиты()
	
	МестоРазмещенияКоманд = Элементы.РанееИзмененныеРеквизиты;
	
	УдаляемыеЭлементы = Новый Массив;
	Для Каждого Настройка Из МестоРазмещенияКоманд.ПодчиненныеЭлементы Цикл
		Если Настройка.Имя = "Заглушка" Тогда
			Продолжить;
		КонецЕсли;
		УдаляемыеЭлементы.Добавить(Настройка);
	КонецЦикла;
	
	Для Каждого Настройка Из УдаляемыеЭлементы Цикл
		Команды.Удалить(Команды[Настройка.Имя]);
		Элементы.Удалить(Настройка);
	КонецЦикла;
	
	Для Каждого Настройка Из ИсторияОперацийСписок Цикл
		НомерКоманды = ИсторияОперацийСписок.Индекс(Настройка);
		ИмяКоманды = МестоРазмещенияКоманд.Имя + "НастройкаИзменений" + НомерКоманды;
		
		КомандаФормы = Команды.Добавить(ИмяКоманды);
		КомандаФормы.Действие = "Подключаемый_УстановитьНастройку";
		КомандаФормы.Заголовок = Настройка.Представление;
		КомандаФормы.ИзменяетСохраняемыеДанные = Ложь;
		
		НовыйЭлемент = Элементы.Добавить(ИмяКоманды, Тип("КнопкаФормы"), МестоРазмещенияКоманд);
		НовыйЭлемент.Вид = ВидКнопкиФормы.КнопкаКоманднойПанели;
		НовыйЭлемент.ИмяКоманды = ИмяКоманды;
	КонецЦикла;
	
	Элементы.Заглушка.Видимость = ИсторияОперацийСписок.Количество() = 0;
	
	Если Не КонтекстныйВызов Тогда
		ЗаполнитьПодменюСоСпискомАлгоритмов();
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПодменюСоСпискомАлгоритмов()
	МестоРазмещенияКоманд = Элементы.Алгоритмы;
	
	УдаляемыеЭлементы = Новый Массив;
	Для Каждого Настройка Из МестоРазмещенияКоманд.ПодчиненныеЭлементы Цикл
		Если Настройка.Имя = "ЗаглушкаАлгоритмы" Тогда
			Продолжить;
		КонецЕсли;
		УдаляемыеЭлементы.Добавить(Настройка);
	КонецЦикла;
	
	Для Каждого Настройка Из УдаляемыеЭлементы Цикл
		Команды.Удалить(Команды[Настройка.Имя]);
		Элементы.Удалить(Настройка);
	КонецЦикла;
	
	Для Каждого Настройка Из ИсторияАлгоритмовСписок Цикл
		НомерКоманды = ИсторияАлгоритмовСписок.Индекс(Настройка);
		ИмяКоманды = МестоРазмещенияКоманд.Имя + "НастройкаИзменений" + НомерКоманды;
		
		КомандаФормы = Команды.Добавить(ИмяКоманды);
		КомандаФормы.Действие = "Подключаемый_УстановитьНастройку";
		КомандаФормы.Заголовок = Настройка.Представление;
		КомандаФормы.ИзменяетСохраняемыеДанные = Ложь;
		
		НовыйЭлемент = Элементы.Добавить(ИмяКоманды, Тип("КнопкаФормы"), МестоРазмещенияКоманд);
		НовыйЭлемент.Вид = ВидКнопкиФормы.КнопкаКоманднойПанели;
		НовыйЭлемент.ИмяКоманды = ИмяКоманды;
	КонецЦикла;
	
	Элементы.ЗаглушкаАлгоритмы.Видимость = ИсторияАлгоритмовСписок.Количество() = 0;
КонецПроцедуры

&НаКлиенте
Процедура УстановитьНастройкуИзменения(Знач Настройка)
	
	СброситьНастройкиИзменения();
	
	ЕстьЗаблокированные = Ложь;
	
	// Для обеспечения обратной совместимости с настройками, сохраненными в БСП 2.1.
	Если ТипЗнч(Настройка) <> Тип("Структура") Тогда
		Настройка = Новый Структура("Реквизиты,ТабличныеЧасти", Настройка, Новый Структура);
	КонецЕсли;
	
	Для Каждого ИзменяемыйРеквизит Из Настройка.Реквизиты Цикл
		СтруктураПоиска = Новый Структура;
		СтруктураПоиска.Вставить("ВидОперации", ИзменяемыйРеквизит.ВидОперации);
		Если ИзменяемыйРеквизит.ВидОперации = 1 Тогда // реквизит объекта
			СтруктураПоиска.Вставить("Имя", ИзменяемыйРеквизит.ИмяРеквизита);
		Иначе
			СтруктураПоиска.Вставить("Свойство", ИзменяемыйРеквизит.Свойство);
		КонецЕсли;
		
		НайденныеСтроки = РеквизитыОбъекта.НайтиСтроки(СтруктураПоиска);
		Если НайденныеСтроки.Количество() > 0 Тогда
			Если НайденныеСтроки[0].ЗаблокированныйРеквизит  Тогда
				ЕстьЗаблокированные = Истина;
				Продолжить;
			КонецЕсли;
			НайденныеСтроки[0].Значение = ИзменяемыйРеквизит.Значение;
			НайденныеСтроки[0].Изменять = Истина;
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого ТабличнаяЧасть Из Настройка.ТабличныеЧасти Цикл
		Для Каждого ИзменяемыйРеквизит Из ТабличнаяЧасть.Значение Цикл
			СтруктураПоиска = Новый Структура;
			СтруктураПоиска.Вставить("Имя", ИзменяемыйРеквизит.Имя);
			Если Элементы.Найти("ТабличнаяЧасть" + ТабличнаяЧасть.Ключ) <> Неопределено Тогда
				НайденныеСтроки = ЭтотОбъект["ТабличнаяЧасть" + ТабличнаяЧасть.Ключ].НайтиСтроки(СтруктураПоиска);
				Если НайденныеСтроки.Количество() > 0 Тогда
					НайденныеСтроки[0].Значение = ИзменяемыйРеквизит.Значение;
					НайденныеСтроки[0].Изменять = Истина;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	Если ЕстьЗаблокированные Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Некоторые реквизиты заблокированы для изменения, изменения не установлены.'"));
	КонецЕсли;
	
	ОбновитьСчетчикиИзменяемыхРеквизитов();
КонецПроцедуры

&НаСервере
Функция ПараметрыВыбораСтрокой(ПараметрыВыбора)
	Результат = "";
	
	Для Каждого ОписаниеПараметраВыбора Из ПараметрыВыбора Цикл
		ТекущийПВСтрока = "[ПолеОтбора];[ТипСтрока];[ЗначениеСтрока]";
		ТипЗначения = ТипЗнч(ОписаниеПараметраВыбора.Значение);
		
		Если ТипЗначения = Тип("ФиксированныйМассив") Тогда
			СтроковоеПредставлениеТипа = "ФиксированныйМассив";
			ЗначениеСтрока = "";
			
			Для Каждого Элемент Из ОписаниеПараметраВыбора.Значение Цикл
				ЗначениеСтрокаШаблон = "[Тип]*[Значение]";
				ЗначениеСтрокаШаблон = СтрЗаменить(ЗначениеСтрокаШаблон, "[Тип]", СтроковоеПредставлениеТипа(ТипЗнч(Элемент)));
				ЗначениеСтрокаШаблон = СтрЗаменить(ЗначениеСтрокаШаблон, "[Значение]", XMLСтрока(Элемент));
				ЗначениеСтрока = ЗначениеСтрока + ?(ПустаяСтрока(ЗначениеСтрока), "", "#") + ЗначениеСтрокаШаблон;
			КонецЦикла;
		Иначе
			СтроковоеПредставлениеТипа = СтроковоеПредставлениеТипа(ТипЗначения);
			ЗначениеСтрока = XMLСтрока(ОписаниеПараметраВыбора.Значение);
		КонецЕсли;
		
		Если Не ПустаяСтрока(ЗначениеСтрока) Тогда
			ТекущийПВСтрока = СтрЗаменить(ТекущийПВСтрока, "[ПолеОтбора]", ОписаниеПараметраВыбора.Имя);
			ТекущийПВСтрока = СтрЗаменить(ТекущийПВСтрока, "[ТипСтрока]", СтроковоеПредставлениеТипа);
			ТекущийПВСтрока = СтрЗаменить(ТекущийПВСтрока, "[ЗначениеСтрока]", ЗначениеСтрока);
			
			Результат = Результат + ТекущийПВСтрока + Символы.ПС;
		КонецЕсли;
	КонецЦикла;
	
	Результат = Лев(Результат, СтрДлина(Результат)-1);
	Возврат Результат;
КонецФункции

&НаСервере
Функция СвязиПараметровВыбораСтрокой(СвязиПараметровВыбора)
	Результат = "";
	
	Для Каждого ОписаниеСвязиПараметровВыбора Из СвязиПараметровВыбора Цикл
		ТекущаяСПВСтрока = "[ИмяПараметра];[ИмяРеквизита]";
		ТекущаяСПВСтрока = СтрЗаменить(ТекущаяСПВСтрока, "[ИмяПараметра]", ОписаниеСвязиПараметровВыбора.Имя);
		ТекущаяСПВСтрока = СтрЗаменить(ТекущаяСПВСтрока, "[ИмяРеквизита]", ОписаниеСвязиПараметровВыбора.ПутьКДанным);
		Результат = Результат + ТекущаяСПВСтрока + Символы.ПС;
	КонецЦикла;
	
	Результат = Лев(Результат, СтрДлина(Результат)-1);
	Возврат Результат;
КонецФункции

&НаСервере
Функция ПредставлениеСвязейПараметровВыбора(СвязиПараметровВыбора, ОбъектМетаданных)
	Результат = "";
	
	СвязанныеРеквизиты = Новый Массив;
	Для Каждого ОписаниеСвязиПараметровВыбора Из СвязиПараметровВыбора Цикл
		ИмяРеквизита = ОписаниеСвязиПараметровВыбора.ПутьКДанным;
		ПредставлениеТабличнойЧасти = "";
		ВладелецРеквизитов = ОбъектМетаданных;
		ЧастиИмени = СтрРазделить(ИмяРеквизита, ".", Истина);
		Если ЧастиИмени.Количество() = 2 Тогда
			ИмяРеквизита = ЧастиИмени[1];
			ИмяТабличнойЧасти = ЧастиИмени[0];
			ВладелецРеквизитов = ОбъектМетаданных.ТабличныеЧасти.Найти(ИмяТабличнойЧасти);
			Если ВладелецРеквизитов <> Неопределено Тогда
				ПредставлениеТабличнойЧасти = ВладелецРеквизитов.Представление();
			КонецЕсли;
		КонецЕсли;
		Если ВладелецРеквизитов <> Неопределено Тогда
			Реквизит = ВладелецРеквизитов.Реквизиты.Найти(ИмяРеквизита);
			Если Реквизит = Неопределено Тогда
				ОписаниеСтандартныхРеквизитов = ВладелецРеквизитов.СтандартныеРеквизиты;// ОписанияСтандартныхРеквизитов
				Для Каждого СтандартныйРеквизит Из ОписаниеСтандартныхРеквизитов Цикл
					Если СтандартныйРеквизит.Имя = ИмяРеквизита Тогда
						Реквизит = СтандартныйРеквизит;
						Прервать;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
			Если Реквизит <> Неопределено Тогда
				ПредставлениеРеквизита = Реквизит.Представление();
				Если Не ПустаяСтрока(ПредставлениеТабличнойЧасти) Тогда
					ПредставлениеРеквизита = ПредставлениеРеквизита + " (" + НСтр("ru = 'таблица'") + " " 
						+ ПредставлениеТабличнойЧасти + ")";
				КонецЕсли;
				СвязанныеРеквизиты.Добавить(ПредставлениеРеквизита);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Если СвязанныеРеквизиты.Количество() > 0 Тогда
		ШаблонПредставленияСвязей = НСтр("ru = 'Зависит от реквизитов: %1.'");
		Если СвязанныеРеквизиты.Количество() = 1 Тогда
			ШаблонПредставленияСвязей = НСтр("ru = 'Зависит от реквизита %1.'");
		КонецЕсли;
		Результат = ПодставитьПараметрыВСтроку(ШаблонПредставленияСвязей, СтрСоединить(СвязанныеРеквизиты, ", "));
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

&НаСервере
Процедура ЗаполнитьСписокТиповОбъектов()
	Элементы.ПредставлениеИзменяемыхОбъектов.СписокВыбора.Очистить();
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	ОбработкаОбъект.ЗаполнитьКоллекциюДоступныхДляИзмененияОбъектов(
		Элементы.ПредставлениеИзменяемыхОбъектов.СписокВыбора, Объект.ПоказыватьСлужебныеРеквизиты);
КонецПроцедуры

&НаКлиенте
Процедура ПояснениеОНастроенныхИзмененияхОбработкаНавигационнойСсылки(Элемент, НавигационнаяСсылкаФорматированнойСтроки, СтандартнаяОбработка)
	Если НавигационнаяСсылкаФорматированнойСтроки = "ПерейтиКНастройкеОтбора" Тогда
		СтандартнаяОбработка = Ложь;
		ПерейтиКНастройкеОтбора();
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПерейтиКНастройкеОтбора()
	Если Не ПустаяСтрока(ВидыИзменяемыхОбъектов) Тогда
		ОписаниеОповещения = Новый ОписаниеОповещения("ПриЗакрытииФормыВыбранныхОбъектов", ЭтотОбъект);
		ОткрытьФорму(ПолноеИмяФормы("ВыбранныеЭлементы"), 
			Новый Структура("ВыбранныеТипы, Настройки", ВидыИзменяемыхОбъектов, КомпоновщикНастроек.Настройки), , , , , ОписаниеОповещения);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция ПараметрыКонструктора(Формула)
	Результат = Новый Структура;
	Результат.Вставить("Формула", Формула);
	Результат.Вставить("ОперандыЗаголовок", НСтр("ru = 'Доступные реквизиты'"));
	Результат.Вставить("Операнды", Операнды());
	Результат.Вставить("Расширенный", Ложь);
	Возврат Результат;
КонецФункции

&НаСервере
Функция Операнды()
	ТаблицаОперандов = Новый ТаблицаЗначений;
	ТаблицаОперандов.Колонки.Добавить("Идентификатор");
	ТаблицаОперандов.Колонки.Добавить("Представление");
	
	Для Каждого ОписаниеРеквизита Из РеквизитыОбъекта Цикл
		Операнд = ТаблицаОперандов.Добавить();
		Операнд.Идентификатор = ОписаниеРеквизита.Представление;
	КонецЦикла;
	
	Возврат ПоместитьВоВременноеХранилище(ТаблицаОперандов, УникальныйИдентификатор);
КонецФункции

&НаКлиенте
Функция ЕстьОшибкаВВыражении(Знач Выражение, ТекстОшибки = "")
	
	Выражение = Сред(Выражение, 2);
	
	Для Каждого ОписаниеРеквизита Из РеквизитыОбъекта Цикл
		Выражение = СтрЗаменить(Выражение, "[" + ОписаниеРеквизита.Представление + "]", """1""");
	КонецЦикла;
	
	Попытка
		Возврат Вычислить(Выражение) = Неопределено;
	Исключение
		ТекстОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		Возврат Истина;
	КонецПопытки;
	
КонецФункции

&НаКлиенте
Процедура ПриРазблокированииРеквизитов(РазблокированныеРеквизиты, ДополнительныеПараметры) Экспорт
	
	Если РазблокированныеРеквизиты = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ТипЗнч(РазблокированныеРеквизиты) = Тип("Массив") И РазблокированныеРеквизиты.Количество() > 0 Тогда
		Отбор = Новый Структура("ЗаблокированныйРеквизит", Истина);
		ЗаблокированныеРеквизитыСтроки = РеквизитыОбъекта.НайтиСтроки(Отбор);
		Для Каждого ОписаниеОперацииСтрока Из ЗаблокированныеРеквизитыСтроки Цикл
			Если ОписаниеОперацииСтрока.ЗаблокированныйРеквизит
			   И РазблокированныеРеквизиты.Найти(ОписаниеОперацииСтрока.Имя) <> Неопределено Тогда
				ОписаниеОперацииСтрока.ЗаблокированныйРеквизит = Ложь;
			КонецЕсли;
		КонецЦикла;
		
	ИначеЕсли РазблокированныеРеквизиты = Истина Тогда
	
		Для Каждого ОписаниеОперацииСтрока Из ЗаблокированныеРеквизитыСтроки Цикл
			ОписаниеОперацииСтрока.ЗаблокированныйРеквизит = Ложь;
		КонецЦикла;
		
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции из базовой функциональности для обеспечения автономности.

// Сохраняет настройку в хранилище общих настроек.
// 
// Параметры:
//   Соответствуют методу ХранилищеОбщихНастроекСохранить.Сохранить, 
//   подробнее - см. параметры процедуры ХранилищеСохранить().
// 
&НаСервереБезКонтекста
Процедура ХранилищеОбщихНастроекСохранить(КлючОбъекта, КлючНастроек, Значение,
	ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено, 
	НужноОбновитьПовторноИспользуемыеЗначения = Ложь)
	
	ХранилищеСохранить(
		ХранилищеОбщихНастроек,
		КлючОбъекта,
		КлючНастроек,
		Значение,
		ОписаниеНастроек,
		ИмяПользователя,
		НужноОбновитьПовторноИспользуемыеЗначения);
	
КонецПроцедуры

// Загружает настройку из хранилища общих настроек.
//
// Параметры:
//   Соответствуют методу ХранилищеОбщихНастроек.Загрузить,
//   подробнее - см. параметры функции ХранилищеЗагрузить().
//
&НаСервереБезКонтекста
Функция ХранилищеОбщихНастроекЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено, 
	ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено)
	
	Возврат ХранилищеЗагрузить(
		ХранилищеОбщихНастроек,
		КлючОбъекта,
		КлючНастроек,
		ЗначениеПоУмолчанию,
		ОписаниеНастроек,
		ИмяПользователя);
	
КонецФункции

&НаСервереБезКонтекста
Процедура ХранилищеСохранить(МенеджерХранилища, КлючОбъекта, КлючНастроек, Значение,
	ОписаниеНастроек, ИмяПользователя, НужноОбновитьПовторноИспользуемыеЗначения)
	
	Если НЕ ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
		Возврат;
	КонецЕсли;
	
	МенеджерХранилища.Сохранить(КлючОбъекта, КлючНастроек(КлючНастроек), Значение, ОписаниеНастроек, ИмяПользователя);
	
	Если НужноОбновитьПовторноИспользуемыеЗначения Тогда
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ХранилищеЗагрузить(МенеджерХранилища, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию,
	ОписаниеНастроек, ИмяПользователя)
	
	Результат = Неопределено;
	
	Если ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
		Результат = МенеджерХранилища.Загрузить(КлючОбъекта, КлючНастроек(КлючНастроек), ОписаниеНастроек, ИмяПользователя);
	КонецЕсли;
	
	Если (Результат = Неопределено) И (ЗначениеПоУмолчанию <> Неопределено) Тогда
		Результат = ЗначениеПоУмолчанию;
	КонецЕсли;

	Возврат Результат;
	
КонецФункции

// Возвращает строку ключа настроек, не превышающую допустимую длину.
// Проверяет длину строки на входе и, в случае превышения 128, преобразует ее конец по алгоритму MD5 в короткий
// вариант, в результате чего строка становится длиной 128 символов.
// Если исходная строка менее 128 символов, она возвращается в неизменном виде.
//
// Параметры:
//  Строка - Строка - строка произвольной длины.
//
&НаСервереБезКонтекста
Функция КлючНастроек(Знач Строка)
	Результат = Строка;
	Если СтрДлина(Строка) > 128 Тогда // Ключ более 128 символов вызовет исключение при обращении к хранилищу настроек.
		Результат = Лев(Строка, 96);
		ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5);
		ХешированиеДанных.Добавить(Сред(Строка, 97));
		Результат = Результат + СтрЗаменить(ХешированиеДанных.ХешСумма, " ", "");
	КонецЕсли;
	Возврат Результат;
КонецФункции

// Возвращает менеджер объекта по полному имени объекта метаданных.
//
// Не обрабатываются точки маршрутов бизнес-процессов.
//
// Параметры:
//  ПолноеИмя    - Строка - полное имя объекта метаданных,
//                 например, "Справочник.Организации".
//
// Возвращаемое значение:
//  СправочникМенеджер, ДокументМенеджер, ОбработкаМенеджер, РегистрСведенийМенеджер - менеджер объекта.
//
&НаСервереБезКонтекста
Функция МенеджерОбъектаПоПолномуИмени(ПолноеИмя)
	Перем КлассОМ, ИмяОМ, Менеджер;
	
	ЧастиИмени = СтрРазделить(ПолноеИмя, ".");
	
	Если ЧастиИмени.Количество() = 2 Тогда
		КлассОМ = ЧастиИмени[0];
		ИмяОМ  = ЧастиИмени[1];
	КонецЕсли;
	
	Если      ВРег(КлассОМ) = "ПЛАНОБМЕНА" Тогда
		Менеджер = ПланыОбмена;
		
	ИначеЕсли ВРег(КлассОМ) = "СПРАВОЧНИК" Тогда
		Менеджер = Справочники;
		
	ИначеЕсли ВРег(КлассОМ) = "ДОКУМЕНТ" Тогда
		Менеджер = Документы;
		
	ИначеЕсли ВРег(КлассОМ) = "ЖУРНАЛДОКУМЕНТОВ" Тогда
		Менеджер = ЖурналыДокументов;
		
	ИначеЕсли ВРег(КлассОМ) = "ПЕРЕЧИСЛЕНИЕ" Тогда
		Менеджер = Перечисления;
		
	ИначеЕсли ВРег(КлассОМ) = "ОТЧЕТ" Тогда
		Менеджер = Отчеты;
		
	ИначеЕсли ВРег(КлассОМ) = "ОБРАБОТКА" Тогда
		Менеджер = Обработки;
		
	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВХАРАКТЕРИСТИК" Тогда
		Менеджер = ПланыВидовХарактеристик;
		
	ИначеЕсли ВРег(КлассОМ) = "ПЛАНСЧЕТОВ" Тогда
		Менеджер = ПланыСчетов;
		
	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВРАСЧЕТА" Тогда
		Менеджер = ПланыВидовРасчета;
		
	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРСВЕДЕНИЙ" Тогда
		Менеджер = РегистрыСведений;
		
	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРНАКОПЛЕНИЯ" Тогда
		Менеджер = РегистрыНакопления;
		
	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРБУХГАЛТЕРИИ" Тогда
		Менеджер = РегистрыБухгалтерии;
		
	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРРАСЧЕТА" Тогда
		Если ЧастиИмени.Количество() = 2 Тогда
			// Регистр расчета
			Менеджер = РегистрыРасчета;
		Иначе
			КлассПодчиненногоОМ = ЧастиИмени[2];
			Если ВРег(КлассПодчиненногоОМ) = "ПЕРЕРАСЧЕТ" Тогда
				// Перерасчет
				Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты;
			Иначе
				ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Неизвестный тип объекта метаданных ""%1""'"), ПолноеИмя);
			КонецЕсли;
		КонецЕсли;
		
	ИначеЕсли ВРег(КлассОМ) = "БИЗНЕСПРОЦЕСС" Тогда
		Менеджер = БизнесПроцессы;
		
	ИначеЕсли ВРег(КлассОМ) = "ЗАДАЧА" Тогда
		Менеджер = Задачи;
		
	ИначеЕсли ВРег(КлассОМ) = "КОНСТАНТА" Тогда
		Менеджер = Константы;
		
	ИначеЕсли ВРег(КлассОМ) = "ПОСЛЕДОВАТЕЛЬНОСТЬ" Тогда
		Менеджер = Последовательности;
	КонецЕсли;
	
	Если Менеджер <> Неопределено Тогда
		Попытка
			Возврат Менеджер[ИмяОМ];
		Исключение
			Менеджер = Неопределено;
		КонецПопытки;
	КонецЕсли;
	
	ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Неизвестный тип объекта метаданных ""%1""'"), ПолноеИмя);
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ПодставитьПараметрыВСтроку(Знач СтрокаПодстановки,
	Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено)
	
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%1", Параметр1);
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%2", Параметр2);
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%3", Параметр3);
	
	Возврат СтрокаПодстановки;
КонецФункции

// Функция ВидОбъектаПоСсылке возвращает имя вида объектов метаданных
// по ссылке на объект.
//
// Не обрабатываются точки маршрутов бизнес-процессов.
//
// Параметры:
//  Ссылка       - ЛюбаяСсылка - элемент справочника, документ, ...
//
// Возвращаемое значение:
//  Строка       - имя вида объектов метаданных, например, "Справочник", "Документ" ...
//
&НаСервереБезКонтекста
Функция ВидОбъектаПоСсылке(Ссылка)
	
	Возврат ВидОбъектаПоТипу(ТипЗнч(Ссылка));
	
КонецФункции 

// Функция возвращает имя вида объектов метаданных по типу объекта.
//
// Не обрабатываются точки маршрутов бизнес-процессов.
//
// Параметры:
//  ТипОбъекта - Тип - тип прикладного объекта, определенный в конфигурации.
//
// Возвращаемое значение:
//  Строка       - имя вида объектов метаданных, например, "Справочник", "Документ" ...
// 
&НаСервереБезКонтекста
Функция ВидОбъектаПоТипу(Тип)
	
	Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "Справочник";
	
	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "Документ";
	
	ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "БизнесПроцесс";
	
	ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "ПланВидовХарактеристик";
	
	ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "ПланСчетов";
	
	ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "ПланВидовРасчета";
	
	ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "Задача";
	
	ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "ПланОбмена";
	
	ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда
		Возврат "Перечисление";
	
	Иначе
		ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Неверный тип значения параметра (%1)'"), Строка(Тип));
	
	КонецЕсли;
	
КонецФункции 

// Проверяет, является ли объект группой элементов.
//
// Параметры:
//  Объект - СправочникОбъект
//         - ДокументОбъект
//         - ЛюбаяСсылка
//         - ДанныеФормыСтруктура
//
// Возвращаемое значение:
//  Булево
//
&НаСервереБезКонтекста
Функция ОбъектЯвляетсяГруппой(Объект)
	
	Если ЗначениеСсылочногоТипа(Объект) Тогда
		Ссылка = Объект;
	Иначе
		Ссылка = Объект.Ссылка;
	КонецЕсли;
	
	МетаданныеОбъекта = Ссылка.Метаданные();
	
	Если ЭтоСправочник(МетаданныеОбъекта) Тогда
		
		Если НЕ МетаданныеОбъекта.Иерархический
		 ИЛИ МетаданныеОбъекта.ВидИерархии
		     <> Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда
			
			Возврат Ложь;
		КонецЕсли;
		
	ИначеЕсли НЕ ЭтоПланВидовХарактеристик(МетаданныеОбъекта) Тогда
		Возврат Ложь;
		
	ИначеЕсли НЕ МетаданныеОбъекта.Иерархический Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если Ссылка <> Объект Тогда
		Возврат Объект.ЭтоГруппа;
	КонецЕсли;
	
	Возврат ЗначениеРеквизитаОбъекта(Ссылка, "ЭтоГруппа");
	
КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Справочник".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - для которого необходимо определить принадлежность к заданному типу.
//
//  Возвращаемое значение:
//   Булево
//
&НаСервереБезКонтекста
Функция ЭтоСправочник(ОбъектМетаданных)
	
	Возврат ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных) = ИмяТипаСправочники();
	
КонецФункции

// Проверка того, что тип имеет ссылочный тип данных.
//
&НаСервереБезКонтекста
Функция ЭтоСсылка(Тип)
	
	Возврат Тип <> Тип("Неопределено") 
		И (Справочники.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ Документы.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ Перечисления.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(Тип)
		ИЛИ Задачи.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип));
	
КонецФункции

// Проверить, что значение имеет ссылочный тип данных.
//
// Параметры:
//  Значение - Произвольный - проверяемое значение.
//
// Возвращаемое значение:
//  Булево       - Истина, если тип значения ссылочный.
//
&НаСервереБезКонтекста
Функция ЗначениеСсылочногоТипа(Значение)
	
	Если Значение = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если Перечисления.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если Задачи.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "План видов характеристик".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - для которого необходимо определить принадлежность к заданному типу.
//
//  Возвращаемое значение:
//   Булево
//
&НаСервереБезКонтекста
Функция ЭтоПланВидовХарактеристик(ОбъектМетаданных)
	
	Возврат ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных) = ИмяТипаПланыВидовХарактеристик();
	
КонецФункции

// Возвращает имя базового типа по переданному значению объекта метаданных.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - по которому необходимо определить базовый тип.
// 
// Возвращаемое значение:
//  Строка - имя базового типа по переданному значению объекта метаданных.
//
&НаСервереБезКонтекста
Функция ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных)
	
	Если Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаДокументы();
		
	ИначеЕсли Метаданные.Справочники.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаСправочники();
		
	ИначеЕсли Метаданные.Перечисления.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПеречисления();
		
	ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаРегистрыСведений();
		
	ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаРегистрыНакопления();
		
	ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаРегистрыБухгалтерии();
		
	ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаРегистрыРасчета();
		
	ИначеЕсли Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПланыОбмена();
		
	ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПланыВидовХарактеристик();
		
	ИначеЕсли Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаБизнесПроцессы();
		
	ИначеЕсли Метаданные.Задачи.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаЗадачи();
		
	ИначеЕсли Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПланыСчетов();
		
	ИначеЕсли Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПланыВидовРасчета();
		
	ИначеЕсли Метаданные.Константы.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаКонстанты();
		
	ИначеЕсли Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаЖурналыДокументов();
		
	ИначеЕсли Метаданные.Последовательности.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаПоследовательности();
		
	ИначеЕсли Метаданные.РегламентныеЗадания.Содержит(ОбъектМетаданных) Тогда
		Возврат ИмяТипаРегламентныеЗадания();
		
	Иначе
		
		Возврат "";
		
	КонецЕсли;
	
КонецФункции

// Возвращает значение для идентификации общего типа "Регистры сведений".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаРегистрыСведений()
	
	Возврат "РегистрыСведений";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Регистры накопления".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаРегистрыНакопления()
	
	Возврат "РегистрыНакопления";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Регистры бухгалтерии".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаРегистрыБухгалтерии()
	
	Возврат "РегистрыБухгалтерии";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Регистры расчета".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаРегистрыРасчета()
	
	Возврат "РегистрыРасчета";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Документы".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаДокументы()
	
	Возврат "Документы";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Справочники".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаСправочники()
	
	Возврат "Справочники";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Перечисления".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПеречисления()
	
	Возврат "Перечисления";
	
КонецФункции

// Возвращает значение для идентификации общего типа "ПланыОбмена".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПланыОбмена()
	
	Возврат "ПланыОбмена";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Планы видов характеристик".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПланыВидовХарактеристик()
	
	Возврат "ПланыВидовХарактеристик";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Бизнес-процессы".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаБизнесПроцессы()
	
	Возврат "БизнесПроцессы";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Задачи".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаЗадачи()
	
	Возврат "Задачи";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Планы счетов".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПланыСчетов()
	
	Возврат "ПланыСчетов";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Планы видов расчета".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПланыВидовРасчета()
	
	Возврат "ПланыВидовРасчета";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Константы".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаКонстанты()
	
	Возврат "Константы";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Журналы документов".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаЖурналыДокументов()
	
	Возврат "ЖурналыДокументов";
	
КонецФункции

// Возвращает значение для идентификации общего типа "Последовательности".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаПоследовательности()
	
	Возврат "Последовательности";
	
КонецФункции

// Возвращает значение для идентификации общего типа "РегламентныеЗадания".
//
// Возвращаемое значение:
//  Строка
//
&НаСервереБезКонтекста
Функция ИмяТипаРегламентныеЗадания()
	
	Возврат "РегламентныеЗадания";
	
КонецФункции

// Возвращает структуру, содержащую значения реквизитов прочитанные из информационной базы
// по ссылке на объект.
// 
//  Если доступа к одному из реквизитов нет, возникнет исключение прав доступа.
//  Если необходимо зачитать реквизит независимо от прав текущего пользователя,
//  то следует использовать предварительный переход в привилегированный режим.
// 
// Параметры:
//  Ссылка    - ЛюбаяСсылка - элемент справочника, документ, ...
//
//  Реквизиты - Строка - имена реквизитов, перечисленные через запятую, в формате
//              требований к свойствам структуры.
//              Например, "Код, Наименование, Родитель".
//            - Структура
//            - ФиксированнаяСтруктура - в качестве ключа передается
//              псевдоним поля для возвращаемой структуры с результатом, а в качестве
//              значения (опционально) фактическое имя поля в таблице.
//              Если значение не определено, то имя поля берется из ключа.
//            - Массив
//            - ФиксированныйМассив - имена реквизитов в формате требований
//              к свойствам структуры.
//
// Возвращаемое значение:
//  Структура - содержит имена (ключи) и значения затребованных реквизитов.
//              Если строка затребованных реквизитов пуста, то возвращается пустая структура.
//
&НаСервереБезКонтекста
Функция ЗначенияРеквизитовОбъекта(Ссылка, Знач Реквизиты)
	
	Если ТипЗнч(Реквизиты) = Тип("Строка") Тогда
		Если ПустаяСтрока(Реквизиты) Тогда
			Возврат Новый Структура;
		КонецЕсли;
		Реквизиты = СтрРазделить(Реквизиты, ",", Ложь);
	КонецЕсли;
	
	СтруктураРеквизитов = Новый Структура;
	Если ТипЗнч(Реквизиты) = Тип("Структура") Или ТипЗнч(Реквизиты) = Тип("ФиксированнаяСтруктура") Тогда
		СтруктураРеквизитов = Реквизиты;
	ИначеЕсли ТипЗнч(Реквизиты) = Тип("Массив") Или ТипЗнч(Реквизиты) = Тип("ФиксированныйМассив") Тогда
		Для Каждого Реквизит Из Реквизиты Цикл
			СтруктураРеквизитов.Вставить(СтрЗаменить(Реквизит, ".", ""), Реквизит);
		КонецЦикла;
	Иначе
		ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Неверный тип второго параметра Реквизиты: %1'"), Строка(ТипЗнч(Реквизиты)));
	КонецЕсли;
	
	ТекстПолей = "";
	Для Каждого КлючИЗначение Из СтруктураРеквизитов Цикл
		ИмяПоля   = ?(ЗначениеЗаполнено(КлючИЗначение.Значение),
		              СокрЛП(КлючИЗначение.Значение),
		              СокрЛП(КлючИЗначение.Ключ));
		
		Псевдоним = СокрЛП(КлючИЗначение.Ключ);
		
		ТекстПолей  = ТекстПолей + ?(ПустаяСтрока(ТекстПолей), "", ",") + "
		|	" + ИмяПоля + " КАК " + Псевдоним;
	КонецЦикла;
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	&ТекстПолей
	|ИЗ
	|	&ИмяТаблицы КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	ПсевдонимЗаданнойТаблицы.Ссылка = &Ссылка
	|";
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ТекстПолей", ТекстПолей);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицы", Ссылка.Метаданные().ПолноеИмя());
	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();
	
	Результат = Новый Структура;
	Для Каждого КлючИЗначение Из СтруктураРеквизитов Цикл
		Результат.Вставить(КлючИЗначение.Ключ);
	КонецЦикла;
	ЗаполнитьЗначенияСвойств(Результат, Выборка);
	
	Возврат Результат;
	
КонецФункции

// Возвращает значение реквизита, прочитанного из информационной базы по ссылке на объект.
//
//  Если доступа к реквизиту нет, возникнет исключение прав доступа.
//  Если необходимо зачитать реквизит независимо от прав текущего пользователя,
//  то следует использовать предварительный переход в привилегированный режим.
//
// Параметры:
//  Ссылка       - ЛюбаяСсылка - элемент справочника, документ, ...
//  ИмяРеквизита - Строка - например, "Код".
//
// Возвращаемое значение:
//  Произвольный    - зависит от типа значения прочитанного реквизита.
//
&НаСервереБезКонтекста
Функция ЗначениеРеквизитаОбъекта(Ссылка, ИмяРеквизита)
	
	Результат = ЗначенияРеквизитовОбъекта(Ссылка, ИмяРеквизита);
	Возврат Результат[СтрЗаменить(ИмяРеквизита, ".", "")];
	
КонецФункции 

// Возвращает ссылку на общий модуль по имени.
//
// Параметры:
//  Имя          - Строка - имя общего модуля, например:
//                 "ОбщегоНазначения",
//                 "ОбщегоНазначенияКлиент".
//
// Возвращаемое значение:
//  ОбщийМодуль
//
&НаКлиентеНаСервереБезКонтекста
Функция ОбщийМодуль(Имя)
	
// АПК:488-выкл "Вычислить" вместо "ОбщегоНазначения.ВычислитьВБезопасномРежиме()", так как это автономная обработка.
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
	Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда
		УстановитьБезопасныйРежим(Истина);
		Модуль = Вычислить(Имя);
	Иначе
		Модуль = Неопределено;
	КонецЕсли;
	
	Если ТипЗнч(Модуль) <> Тип("ОбщийМодуль") Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Общий модуль ""%1"" не существует.'"), Имя);
	КонецЕсли;
#Иначе
	Модуль = Вычислить(Имя);
	Если ТипЗнч(Модуль) <> Тип("ОбщийМодуль") Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Общий модуль ""%1"" не существует.'"), Имя);
	КонецЕсли;
#КонецЕсли
// АПК:488-вкл
	
	Возврат Модуль;
	
КонецФункции

// Возвращает Истина, если подсистема существует.
//
// Параметры:
//  ПолноеИмяПодсистемы - Строка - полное имя объекта метаданных подсистема без слов "Подсистема.".
//                        Например: "СтандартныеПодсистемы.БазоваяФункциональность".
//
// Пример вызова необязательной подсистемы:
//
//  Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
//  	МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
//  	МодульУправлениеДоступом.<Имя метода>();
//  КонецЕсли;
//
// Возвращаемое значение:
//  Булево
//
&НаСервере
Функция ПодсистемаСуществует(ПолноеИмяПодсистемы)
	
	Если Не ВерсияБСПСоответствуетТребованиям() Тогда
		Возврат Ложь;
	КонецЕсли;
	
	ИменаПодсистем = ИменаПодсистем();
	Возврат ИменаПодсистем.Получить(ПолноеИмяПодсистемы) <> Неопределено;
	
КонецФункции

// Возвращает соответствие имен подсистем и значения Истина;
&НаСервереБезКонтекста
Функция ИменаПодсистем()
	
	Возврат Новый ФиксированноеСоответствие(ИменаПодчиненныхПодсистем(Метаданные));
	
КонецФункции

&НаСервереБезКонтекста
Функция ИменаПодчиненныхПодсистем(РодительскаяПодсистема)
	
	Имена = Новый Соответствие;
	
	Для Каждого ТекущаяПодсистема Из РодительскаяПодсистема.Подсистемы Цикл
		
		Имена.Вставить(ТекущаяПодсистема.Имя, Истина);
		ИменаПодчиненных = ИменаПодчиненныхПодсистем(ТекущаяПодсистема);
		
		Для каждого ИмяПодчиненной Из ИменаПодчиненных Цикл
			Имена.Вставить(ТекущаяПодсистема.Имя + "." + ИмяПодчиненной.Ключ, Истина);
		КонецЦикла;
	КонецЦикла;
	
	Возврат Имена;
	
КонецФункции

// Возвращает строковое представление типа. 
// Для ссылочных типов возвращает в формате "СправочникСсылка.ИмяОбъекта" или "ДокументСсылка.ИмяОбъекта".
// Для остальных типов приводит тип к строке, например "Число".
//
&НаСервереБезКонтекста
Функция СтроковоеПредставлениеТипа(Тип)
	
	Представление = "";
	
	Если ЭтоСсылка(Тип) Тогда
	
		ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
		ИмяОбъекта = СтрРазделить(ПолноеИмя, ".")[1];
		
		Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "СправочникСсылка";
		
		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ДокументСсылка";
		
		ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "БизнесПроцессСсылка";
		
		ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовХарактеристикСсылка";
		
		ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланСчетовСсылка";
		
		ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовРасчетаСсылка";
		
		ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ЗадачаСсылка";
		
		ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланОбменаСсылка";
		
		ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПеречислениеСсылка";
		
		КонецЕсли;
		
		Результат = ?(Представление = "", Представление, Представление + "." + ИмяОбъекта);
		
	ИначеЕсли Тип = Тип("Неопределено") Тогда
		
		Результат = "Неопределено";
		
	ИначеЕсли Тип = Тип("Строка") Тогда
		Результат = "Строка";

	ИначеЕсли Тип = Тип("Число") Тогда
		Результат = "Число";

	ИначеЕсли Тип = Тип("Булево") Тогда
		Результат = "Булево";

	ИначеЕсли Тип = Тип("Дата") Тогда
		Результат = "Дата";
	
	Иначе
		
		Результат = Строка(Тип);
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

//	Преобразует таблицу значений в массив.
//	Может использоваться для передачи на клиента данных, полученных
//	на сервере в виде таблицы значений в том случае, если таблица
//	значений содержит только такие значения, которые могут
//  быть переданы на клиента.
//
//	Полученный массив содержит структуры, каждая из которых повторяет
//	структуру колонок таблицы значений.
//
//	Не рекомендуется использовать для преобразования таблиц значений
//	с большим количеством строк.
//
//	Параметры:
//    ТаблицаЗначений - ТаблицаЗначений 
//
//	Возвращаемое значение:
//    Массив
//
&НаСервереБезКонтекста
Функция ТаблицаЗначенийВМассив(ТаблицаЗначений)
	
	Массив = Новый Массив();
	СтруктураСтрокой = "";
	НужнаЗапятая = Ложь;
	Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
		Если НужнаЗапятая Тогда
			СтруктураСтрокой = СтруктураСтрокой + ",";
		КонецЕсли;
		СтруктураСтрокой = СтруктураСтрокой + Колонка.Имя;
		НужнаЗапятая = Истина;
	КонецЦикла;
	Для Каждого Строка Из ТаблицаЗначений Цикл
		НоваяСтрока = Новый Структура(СтруктураСтрокой);
		ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
		Массив.Добавить(НоваяСтрока);
	КонецЦикла;
	Возврат Массив;

КонецФункции

// Форматирует строку в соответствии с заданным шаблоном.
// Возможные значения тегов выделения:
//	<b> Строка </b> - выделяет строку жирным шрифтом.
//	<a href = "Ссылка"> Строка </a>
//
// Пример:
//	Минимальная версия программы <b>1.1</b>. <a href = "Обновление">Обновите</a> программу.
//
// Возвращаемое значение:
//  ФорматированнаяСтрока
//
&НаСервереБезКонтекста
Функция ФорматированнаяСтрока(Знач Строка)
	
	СтрокиСВыделением = Новый СписокЗначений;
	Пока СтрНайти(Строка, "<b>") <> 0 Цикл
		НачалоВыделения = СтрНайти(Строка, "<b>");
		СтрокаДоОткрывающегоТега = Лев(Строка, НачалоВыделения - 1);
		СтрокиСВыделением.Добавить(СтрокаДоОткрывающегоТега);
		СтрокаПослеОткрывающегоТега = Сред(Строка, НачалоВыделения + 3);
		КонецВыделения = СтрНайти(СтрокаПослеОткрывающегоТега, "</b>");
		ВыделенныйФрагмент = Лев(СтрокаПослеОткрывающегоТега, КонецВыделения - 1);
		СтрокиСВыделением.Добавить(ВыделенныйФрагмент,, Истина);
		СтрокаПослеВыделения = Сред(СтрокаПослеОткрывающегоТега, КонецВыделения + 4);
		Строка = СтрокаПослеВыделения;
	КонецЦикла;
	СтрокиСВыделением.Добавить(Строка);
	
	СтрокиСоСсылками = Новый СписокЗначений;
	Для Каждого ЧастьСтроки Из СтрокиСВыделением Цикл
		
		Строка = ЧастьСтроки.Значение;
		
		Если ЧастьСтроки.Пометка Тогда
			СтрокиСоСсылками.Добавить(Строка,, Истина);
			Продолжить;
		КонецЕсли;
		
		НачалоВыделения = СтрНайти(Строка, "<a href = ");
		Пока НачалоВыделения <> 0 Цикл
			СтрокаДоОткрывающегоТега = Лев(Строка, НачалоВыделения - 1);
			СтрокиСоСсылками.Добавить(СтрокаДоОткрывающегоТега, );
			
			СтрокаПослеОткрывающегоТега = Сред(Строка, НачалоВыделения + 9);
			ЗакрывающийТег = СтрНайти(СтрокаПослеОткрывающегоТега, ">");
			
			Ссылка = СокрЛП(Лев(СтрокаПослеОткрывающегоТега, ЗакрывающийТег - 2));
			Если СтрНачинаетсяС(Ссылка, """") Тогда
				Ссылка = Сред(Ссылка, 2, СтрДлина(Ссылка) - 1);
			КонецЕсли;
			Если СтрЗаканчиваетсяНа(Ссылка, """") Тогда
				Ссылка = Сред(Ссылка, 1, СтрДлина(Ссылка) - 1);
			КонецЕсли;
			
			СтрокаПослеСсылки = Сред(СтрокаПослеОткрывающегоТега, ЗакрывающийТег + 1);
			КонецВыделения = СтрНайти(СтрокаПослеСсылки, "</a>");
			ТекстСсылки = Лев(СтрокаПослеСсылки, КонецВыделения - 1);
			СтрокиСоСсылками.Добавить(ТекстСсылки, Ссылка);
			
			СтрокаПослеВыделения = Сред(СтрокаПослеСсылки, КонецВыделения + 4);
			Строка = СтрокаПослеВыделения;
			
			НачалоВыделения = СтрНайти(Строка, "<a href = ");
		КонецЦикла;
		СтрокиСоСсылками.Добавить(Строка);
		
	КонецЦикла;
	
	МассивСтроки = Новый Массив;
	Для Каждого ЧастьСтроки Из СтрокиСоСсылками Цикл
		
		Если ЧастьСтроки.Пометка Тогда
			//@skip-check new-font
			МассивСтроки.Добавить(Новый ФорматированнаяСтрока(ЧастьСтроки.Значение, Новый Шрифт(,,Истина))); // АПК:1345 - автономная обработка не может использовать стили
		ИначеЕсли Не ПустаяСтрока(ЧастьСтроки.Представление) Тогда
			МассивСтроки.Добавить(Новый ФорматированнаяСтрока(ЧастьСтроки.Значение,,,, ЧастьСтроки.Представление));
		Иначе
			МассивСтроки.Добавить(ЧастьСтроки.Значение);
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Новый ФорматированнаяСтрока(МассивСтроки); // АПК:1356 - можно использовать составную форматированную строку, так как массив строк формируется из переданного в функцию текста.
	
КонецФункции

// Формирует представление числа для определенного языка и параметров числа.
//
// Параметры:
//  Шаблон          - Строка - строка, содержит перечисленные через точку с запятой 6 форм строки
//                             для каждой категории числительного: 
//                             %1 обозначает позицию числа;
//  Число           - Число - число, которое будет подставлено в строку вместо параметра "%1".
//  Вид             - ВидЧисловогоЗначения - определяет вид числового значения, для которого формируется представление. 
//                             Количественное (по умолчанию) или Порядковое.
//  ФорматнаяСтрока - Строка - строка параметров форматирования. См. аналогичный параметр в СтрокаСЧислом. 
//
// Возвращаемое значение:
//  Строка - представление строки числа в требуемой форме.
//
// Пример:
//  
//  Строка = СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка(
//		НСтр("ru=';остался %1 день;;осталось %1 дня;осталось %1 дней;осталось %1 дня';
//		     |en=';left %1 day;;;;left %1 days'"), 
//		0.05,, "ЧДЦ=1");
// 
&НаСервереБезКонтекста
Функция СтрокаСЧисломДляЛюбогоЯзыка(Шаблон, Число, Вид = Неопределено, ФорматнаяСтрока = "ЧН=0;")

	Если ПустаяСтрока(Шаблон) Тогда
		Возврат Формат(Число, ФорматнаяСтрока); 
	КонецЕсли;

	Если Вид = Неопределено Тогда
		Вид = ВидЧисловогоЗначения.Количественное;
	КонецЕсли;

	Возврат СтрокаСЧислом(Шаблон, Число, Вид, ФорматнаяСтрока);

КонецФункции

// Возвращает признак, является ли конфигурация базовой.
//
// Возвращаемое значение:
//   Булево   - Истина, если конфигурация - базовая.
//
&НаСервереБезКонтекста
Функция ЭтоБазоваяВерсияКонфигурации()
	
	Возврат СтрНайти(ВРег(Метаданные.Имя), "БАЗОВАЯ") > 0;
	
КонецФункции

// Возвращает признак включения условного разделения.
// В случае вызова в неразделенной конфигурации возвращает Ложь.
//
&НаСервереБезКонтекста
Функция РазделениеВключено()
	
	ДоступнаРаботаВМоделиСервиса = Метаданные.ФункциональныеОпции.Найти("РаботаВМоделиСервиса");
	Если ДоступнаРаботаВМоделиСервиса <> Неопределено Тогда
		ИмяОпции = "РаботаВМоделиСервиса";
		Возврат ЭтоРазделеннаяКонфигурация() И ПолучитьФункциональнуюОпцию(ИмяОпции);
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

// Возвращает признак наличия в конфигурации общих реквизитов-разделителей.
//
// Возвращаемое значение:
//   Булево
//
&НаСервереБезКонтекста
Функция ЭтоРазделеннаяКонфигурация()
	
	ЕстьРазделители = Ложь;
	Для каждого ОбщийРеквизит Из Метаданные.ОбщиеРеквизиты Цикл
		Если ОбщийРеквизит.РазделениеДанных = Метаданные.СвойстваОбъектов.РазделениеДанныхОбщегоРеквизита.Разделять Тогда
			ЕстьРазделители = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ЕстьРазделители;
	
КонецФункции

&НаСервере
Функция ВерсияБСПСоответствуетТребованиям()
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	Возврат ОбработкаОбъект.ВерсияБСПСоответствуетТребованиям();
КонецФункции

&НаСервере
Процедура ПроверитьВерсиюИРежимСовместимостиПлатформы()
	
	Информация = Новый СистемнаяИнформация;
	Если Не (Лев(Информация.ВерсияПриложения, 3) = "8.3"
		И (Метаданные.РежимСовместимости = Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать
		Или (Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.Версия8_1
		И Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.Версия8_2_13
		И Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости["Версия8_2_16"]
		И Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости["Версия8_3_1"]
		И Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости["Версия8_3_2"]))) Тогда
		
		ВызватьИсключение НСтр("ru = 'Обработка предназначена для запуска на версии платформы
			|1С:Предприятие 8.3 с отключенным режимом совместимости или выше'");
		
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция КартинкаВидыОпераций()
	Если ВерсияБСПСоответствуетТребованиям() Тогда
		Возврат БиблиотекаКартинок["ВидыОпераций"];
	Иначе
		Возврат Новый Картинка;
	КонецЕсли;
КонецФункции

&НаКлиенте
Процедура РеквизитыОбъекта1НачалоПеретаскивания(Элемент, ПараметрыПеретаскивания, Выполнение)
	ПараметрыПеретаскивания.Значение = "Объект." + Элемент.ТекущиеДанные.Имя;
	// Вставить содержимое обработчика.
КонецПроцедуры

&НаКлиенте
Процедура ПредставлениеИзменяемыхОбъектовАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	ПолеВводаАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
КонецПроцедуры

&НаКлиенте
Процедура ПолеВводаАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	ДанныеВыбора = ДанныеВыбора(Текст, Элемент.СписокВыбора);
	СтандартнаяОбработка = Не ЗначениеЗаполнено(Текст);
КонецПроцедуры

&НаКлиенте
Функция ДанныеВыбора(Строка, СписокВыбора)
	
	Результат = Новый СписокЗначений;
	
	Если Не ЗначениеЗаполнено(Строка) Тогда
		Возврат Результат;
	КонецЕсли;
	
	Для Каждого Элемент Из СписокВыбора Цикл
		ПредставлениеЭлемента = Элемент.Представление;
		
		СтрокаПоиска = ПредставлениеЭлемента;
		
		ФорматированныеСтроки = Новый Массив;
		Для Каждого Подстрока Из СтрРазделить(Строка, " ", Ложь) Цикл
			Позиция = СтрНайти(НРег(СтрокаПоиска), НРег(Подстрока));
			Если Позиция = 0 Тогда
				ФорматированныеСтроки = Неопределено;
				Прервать;
			КонецЕсли;
			
			ПодстрокаДоВхождения = Лев(СтрокаПоиска, Позиция - 1);
			ПодстрокаВхождения = Сред(СтрокаПоиска, Позиция, СтрДлина(Подстрока));
			СтрокаПоиска = Сред(СтрокаПоиска, Позиция + СтрДлина(Подстрока));
			
			ФорматированныеСтроки.Добавить(ПодстрокаДоВхождения);
			//@skip-check new-font
			//@skip-check new-color
			ФорматированныеСтроки.Добавить(Новый ФорматированнаяСтрока(ПодстрокаВхождения,
				Новый Шрифт( , , Истина), Новый Цвет(0,128,0))); // АПК:1345 АПК:1346 - автономная обработка не может использовать стили
		КонецЦикла;
		
		Если Не ЗначениеЗаполнено(ФорматированныеСтроки) Тогда
			Продолжить;
		КонецЕсли;
		
		ФорматированныеСтроки.Добавить(СтрокаПоиска);
		СтрокаСПодсветкой = Новый ФорматированнаяСтрока(ФорматированныеСтроки); // АПК:1356 - можно использовать составную форматированную строку, так как массив строк формируется из переданного в функцию текста.
		
		Результат.Добавить(Элемент.Значение, СтрокаСПодсветкой);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Функция ДоступностьОбъектов()
	
	ДоступностьОбъектов = Новый Соответствие;
	Для Каждого ФункциональнаяОпция Из Метаданные.ФункциональныеОпции Цикл
		Если Не Метаданные.Константы.Содержит(ФункциональнаяОпция.Хранение) Тогда
			Продолжить;
		КонецЕсли;
		Значение = ПолучитьФункциональнуюОпцию(ФункциональнаяОпция.Имя, Новый Структура);
		Для Каждого Элемент Из ФункциональнаяОпция.Состав Цикл
			Если Элемент.Объект = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			Если Значение = Истина Тогда
				ДоступностьОбъектов.Вставить(Элемент.Объект, Истина);
			Иначе
				Если ДоступностьОбъектов[Элемент.Объект] = Неопределено Тогда
					ДоступностьОбъектов.Вставить(Элемент.Объект, Ложь);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	Возврат ДоступностьОбъектов;
	
КонецФункции

&НаСервере
Функция ЭтоПолноправныйПользователь()
	
	Если ВерсияБСПСоответствуетТребованиям() Тогда
		МодульПользователи = ОбщийМодуль("Пользователи");
		Возврат МодульПользователи.ЭтоПолноправныйПользователь();
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

&НаКлиенте
Процедура РедактироватьФормулу()
	ТекущиеДанные = Элементы.РеквизитыОбъекта.ТекущиеДанные;
	ОписаниеОповещения = Новый ОписаниеОповещения("РеквизитыОбъектаЗначениеЗавершениеВыбора", ЭтотОбъект, ТекущиеДанные);
	ОткрытьФорму(ПолноеИмяФормы("РедактированиеФормулы"), ПараметрыКонструктора(ТекущиеДанные.Значение), , , , ,
		ОписаниеОповещения);
КонецПроцедуры

#КонецОбласти